/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs
7 548 строк
312 KB
Julien Couvreur
Extensions: address some diagnostic quality issues (#80827)
24 окт 2025, 07:50
Не верифицирован
24 окт 2025, 07:50
fa5d81f
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Linq; using System.Reflection; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Basic.Reference.Assemblies; using Utils = Microsoft.CodeAnalysis.CSharp.UnitTests.CompilationUtils; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols { public class GenericConstraintTests : CSharpTestBase { [ClrOnlyFact] public void LoadAndPersist() { var source = @"class A<T> where T : struct { } class B<T> where T : class { } interface IA<T> { } interface IB<T> where T : IA<T> { } class C<T> where T : IB<T>, IA<T>, new() { } class D<T> where T : A<int>, new() { }"; Action<ModuleSymbol> validator = module => { var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("A"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("B"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.ReferenceType, false, true, "object", "object"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("IA"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("IB"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "IA<T>"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.Constructor, false, false, "object", "object", "IB<T>", "IA<T>"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("D"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.Constructor, false, true, "A<int>", "A<int>", "A<int>"); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } [ClrOnlyFact] public void OverriddenMethods() { var source = @"class A<T> { internal virtual void M<U>() where U : T { } } class B0<T> : A<T> { internal override void M<U>() { } } class B1 : A<int> { internal override void M<U>() { } }"; Action<ModuleSymbol> validator = module => { var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("A"); var method = type.GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("B0"); method = type.GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("B1"); method = type.GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, true, false, "ValueType", "int", "int"); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } [ClrOnlyFact] public void ExplicitInterfaceMethods() { var source = @"interface I<T, U> { void M<V>() where V : T, U; } class C : I<C, object> { void I<C, object>.M<V>() { } }"; Action<ModuleSymbol> validator = module => { var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var method = type.GetMethod("I<C,System.Object>.M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, true, "C", "C", "C"); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } /// <summary> /// SourceMemberMethodSymbol binds parameters and type parameters /// of partial methods early - in the constructor. Ensure constraints for /// overridden methods are handled in these cases. /// </summary> [ClrOnlyFact] public void PartialClassOverriddenMethods() { var source = @"interface I<T> { } abstract partial class A<T> { internal abstract void M1<U>(T t) where U : T; } abstract partial class A<T> { internal abstract void M2<U>(U u) where U : I<T>; } partial class B<T> : A<T> { internal override void M1<U>(T t) { } } partial class B<T> : A<T> { internal override void M2<U>(U u) { } }"; Action<ModuleSymbol> validator = module => { var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("A"); var method = type.GetMember<MethodSymbol>("M1"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T"); Utils.CheckSymbol(method, "void A<T>.M1<U>(T t)"); method = type.GetMember<MethodSymbol>("M2"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "I<T>"); Utils.CheckSymbol(method, "void A<T>.M2<U>(U u)"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("B"); method = type.GetMember<MethodSymbol>("M1"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T"); Utils.CheckSymbol(method, "void B<T>.M1<U>(T t)"); Utils.CheckSymbol(method.OverriddenMethod, "void A<T>.M1<U>(T t)"); method = type.GetMember<MethodSymbol>("M2"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "I<T>"); Utils.CheckSymbol(method, "void B<T>.M2<U>(U u)"); Utils.CheckSymbol(method.OverriddenMethod, "void A<T>.M2<U>(U u)"); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } [ClrOnlyFact] public void ConstraintWithTypeParameter() { var source = @"interface I<T> { } struct S<T> where T : I<T> { void M<U, V>() where U : V where V : I<U> { } } delegate void D<T>() where T : I<T>;"; CompileAndVerify(source); } [ClrOnlyFact] public void ConstraintWithContainingType() { var source = @"interface IA<T> { } class C<T> where T : IA<C<T>> { } interface IB<T> where T : IB<T> { }"; CompileAndVerify(source); } [ClrOnlyFact] public void ConstraintWithSameType() { var source = @"interface I<T> where T : I<T> { } class C<T, U> where T : C<T, U> { }"; CompileAndVerify(source); } [ClrOnlyFact] public void BaseWithSameType() { var source = @"interface IA<T> { } interface IB<T> : IA<IB<T>> where T : IA<T> { } class A<T> { } class B<T> : A<B<T>> where T : A<T> { }"; CompileAndVerify(source); } [Fact] public void ConstraintWithNestedInterfaceTypeArgument() { var source = @"interface A1<T> where T : A2 { } interface A2 { } class B1 : A1<B1.B2> // valid { internal interface B2 : A2 { } } class C1 : A1<C1.C2> // invalid { internal interface C2 { } }"; CreateCompilation(source).VerifyDiagnostics( // (7,7): error CS0311: The type 'C1.C2' cannot be used as type parameter 'T' in the generic type or method 'A1<T>'. There is no implicit reference conversion from 'C1.C2' to 'A2'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "C1").WithArguments("A1<T>", "A2", "T", "C1.C2").WithLocation(7, 7)); } [Fact] public void ConstraintWithNestedClassTypeArgument() { var source = @"abstract class A1<T> where T : A1<T>.A2 { internal class A2 { } } class B1 : A1<B1.B2> // valid { internal class B2 : A2 { } } class C1 : A1<C1.C2> // invalid { internal class C2 { } }"; CreateCompilation(source).VerifyDiagnostics( // (9,7): error CS0311: The type 'C1.C2' cannot be used as type parameter 'T' in the generic type or method 'A1<T>'. There is no implicit reference conversion from 'C1.C2' to 'A1<C1.C2>.A2'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "C1").WithArguments("A1<T>", "A1<C1.C2>.A2", "T", "C1.C2").WithLocation(9, 7)); } [WorkItem(542616, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542616")] [Fact] public void NewConstraintWithPrivateConstructorErr() { var metadatasrc = @"public class PrivateCtorClass { private PrivateCtorClass() { } }"; var source = @"public class Test { public static int Main() { var g1 = new Gen<PrivateCtorClass>(); // CS0310 return 0; } } public class Gen<T> where T : new() { public T t;} "; var comp1 = CreateCompilation(metadatasrc); var comp2 = CreateCompilation(source, new MetadataReference[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics( // (5,26): error CS0310: 'PrivateCtorClass' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Gen<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "PrivateCtorClass").WithArguments("Gen<T>", "T", "PrivateCtorClass").WithLocation(5, 26)); } [WorkItem(542617, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542617")] [Fact] public void InterfaceConstraintWithClassTypeArgumentErr() { var source = @"public interface InterfaceConstraint { } public class ViolateInterfaceConstraint { } public class Gen<T> where T : InterfaceConstraint { public void Meth(Gen<ViolateInterfaceConstraint>.Nested[] Param) {} // CS0311 public class Nested { } } "; CreateCompilation(source).VerifyDiagnostics( // (6,63): error CS0311: The type 'ViolateInterfaceConstraint' cannot be used as type parameter 'T' in the generic type or method 'Gen<T>'. // There is no implicit reference conversion from 'ViolateInterfaceConstraint' to 'InterfaceConstraint'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "Param"). WithArguments("Gen<T>", "InterfaceConstraint", "T", "ViolateInterfaceConstraint").WithLocation(6, 63)); } [WorkItem(542617, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542617")] [Fact] public void NestedViolationsInvolvingArraysAndPointers() { var source = @"class A<T> where T : struct { internal class B1 { } private class B2 { } } unsafe interface I { void M1(A<A<int>*>.B1 o); void M2(A<string>.B1** o); void M3(A<A<int>.B2>.B1* o); void M4(A<A<int>[]>.B1 o); void M5(A<string>.B1[][] o); void M6(A<A<int>.B2>.B1[] o); void M7(A<A<int>.B1[]>.B1 o); }"; CreateCompilation(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (10,22): error CS0122: 'A<int>.B2' is inaccessible due to its protection level // void M3(A<A<int>.B2>.B1* o); Diagnostic(ErrorCode.ERR_BadAccess, "B2").WithArguments("A<int>.B2").WithLocation(10, 22), // (13,22): error CS0122: 'A<int>.B2' is inaccessible due to its protection level // void M6(A<A<int>.B2>.B1[] o); Diagnostic(ErrorCode.ERR_BadAccess, "B2").WithArguments("A<int>.B2").WithLocation(13, 22), // (14,31): error CS0453: The type 'A<int>.B1[]' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' // void M7(A<A<int>.B1[]>.B1 o); Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "o").WithArguments("A<T>", "T", "A<int>.B1[]").WithLocation(14, 31), // (9,28): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('A<string>.B1') // void M2(A<string>.B1** o); Diagnostic(ErrorCode.WRN_ManagedAddr, "o").WithArguments("A<string>.B1").WithLocation(9, 28), // (9,28): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' // void M2(A<string>.B1** o); Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "o").WithArguments("A<T>", "T", "string").WithLocation(9, 28), // (10,30): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('A<A<int>.B2>.B1') // void M3(A<A<int>.B2>.B1* o); Diagnostic(ErrorCode.WRN_ManagedAddr, "o").WithArguments("A<A<int>.B2>.B1").WithLocation(10, 30), // (11,28): error CS0453: The type 'A<int>[]' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' // void M4(A<A<int>[]>.B1 o); Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "o").WithArguments("A<T>", "T", "A<int>[]").WithLocation(11, 28), // (12,30): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' // void M5(A<string>.B1[][] o); Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "o").WithArguments("A<T>", "T", "string").WithLocation(12, 30), // (8,27): error CS0306: The type 'A<int>*' may not be used as a type argument // void M1(A<A<int>*>.B1 o); Diagnostic(ErrorCode.ERR_BadTypeArgument, "o").WithArguments("A<int>*").WithLocation(8, 27), // (8,27): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('A<int>') // void M1(A<A<int>*>.B1 o); Diagnostic(ErrorCode.WRN_ManagedAddr, "o").WithArguments("A<int>").WithLocation(8, 27)); } [WorkItem(542618, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542618")] [Fact] public void AllowReferenceTypeVolatileField() { var source = @"public interface I {} public class C : I{} class G<T> where T : C { public volatile T Fld = default(T); } "; CreateCompilation(source).VerifyDiagnostics(); } /// <summary> /// Implicit implementations must specify constraints. /// </summary> [ClrOnlyFact] public void ImplicitImplementation() { var source = @"interface I<T> { void M1<U>() where U : T; void M2<U>() where U : struct, T; void M3<U>() where U : I<T>; } class A<T> : I<T> { public void M1<U>() where U : T { } public void M2<U>() where U : struct, T { } public void M3<U>() where U : I<T> { } } class B : I<object> { public void M1<T>() { } public void M2<T>() where T : struct { } public void M3<T>() where T : I<object> { } }"; // TODO: Verify constraints for implementations are emitted correctly. CompileAndVerify(source); } /// <summary> /// Explicit implementations do not specify constraints. /// </summary> [ClrOnlyFact] public void ExplicitImplementation() { var source = @"interface I<T> { void M1<U>() where U : T; void M2<U>() where U : class, T; void M3<U>() where U : I<U>; void M4<U, V>() where U : V; } class A<T> : I<T> { void I<T>.M1<U>() { } void I<T>.M2<U>() { } void I<T>.M3<U>() { } void I<T>.M4<U, V>() { } } class B : I<string> { void I<string>.M1<U>() { } void I<string>.M2<U>() { } void I<string>.M3<U>() { } void I<string>.M4<U, V>() { } } class C : I<object> { void I<object>.M1<T>() { } void I<object>.M2<T>() { } void I<object>.M3<T>() { } void I<object>.M4<T, U>() { } }"; // TODO: Verify constraints for implementations are emitted correctly. CompileAndVerify(source); } /// <summary> /// Dev10 reports constraint violations at every reference to an /// interface type, including in explicit member declarations. /// </summary> [Fact] public void ExplicitImplementationInterfaceConstraintViolations() { var source = @"interface I<T, U> where T : class where U : struct { void M<V>(); object P { get; set; } } class C : I<int, object> { void I<int, object>.M<V>() { } object I<int, object>.P { get; set; } }"; CreateCompilation(source).VerifyDiagnostics( // (8,7): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T, U>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C").WithArguments("I<T, U>", "T", "int").WithLocation(8, 7), // (8,7): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'I<T, U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C").WithArguments("I<T, U>", "U", "object").WithLocation(8, 7), // (10,10): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T, U>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "I<int, object>").WithArguments("I<T, U>", "T", "int").WithLocation(10, 10), // (10,10): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'I<T, U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "I<int, object>").WithArguments("I<T, U>", "U", "object").WithLocation(10, 10), // (11,12): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T, U>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "I<int, object>").WithArguments("I<T, U>", "T", "int").WithLocation(11, 12), // (11,12): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'I<T, U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "I<int, object>").WithArguments("I<T, U>", "U", "object").WithLocation(11, 12)); } /// <summary> /// Similar to ExplicitImplementationInterfaceConstraintViolations but /// where the constraint violation involves a reference to the containing type. /// </summary> [WorkItem(542948, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542948")] [Fact] public void ExplicitImplementationInterfaceConstraintViolationsOnContainer() { var source = @"delegate void D(); class A { internal interface I<T> where T : new() { void M(); object P { get; } object this[object index] { get; } event D E; } } abstract class B : A.I<B> { void A.I<B>.M() { } object A.I<B>.P { get { return null; } } object A.I<B>.this[object index] { get { return null; } } event D A.I<B>.E { add { } remove { } } }"; CreateCompilation(source).VerifyDiagnostics( // (12,16): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'A.I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "B").WithArguments("A.I<T>", "T", "B").WithLocation(12, 16), // (14,10): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'A.I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "A.I<B>").WithArguments("A.I<T>", "T", "B").WithLocation(14, 10), // (15,12): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'A.I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "A.I<B>").WithArguments("A.I<T>", "T", "B").WithLocation(15, 12), // (16,12): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'A.I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "A.I<B>").WithArguments("A.I<T>", "T", "B").WithLocation(16, 12), // (17,13): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'A.I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "A.I<B>").WithArguments("A.I<T>", "T", "B").WithLocation(17, 13)); } /// <summary> /// Ensure generic methods are handled in an explicit /// implementation where the interface method does not exist. /// </summary> [Fact] public void ExplicitImplementationNoSuchMethod() { var source = @"interface I<T> where T : class { void M1<U>(); } class C : I<string> { void I<string>.M2<U>() { } }"; CreateCompilation(source).VerifyDiagnostics( // (7,20): error CS0539: 'C.M2<U>()' in explicit interface declaration is not a member of interface Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M2").WithArguments("C.M2<U>()"), // (5,11): error CS0535: 'C' does not implement interface member 'I<string>.M1<U>()' Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I<string>").WithArguments("C", "I<string>.M1<U>()")); } /// <summary> /// Constraints on base types, interfaces, and method parameters /// and return types are all checked outside of BindType to avoid /// cycles. Verify that constraints are checked in those cases. /// </summary> [Fact] public void BasesInterfacesParametersAndReturnTypes() { var source = @"interface I<T> where T : class { } class A<T> where T : class { internal interface I { } internal class C { } } class B { internal interface I<U> where U : struct { } internal class C<U> where U : struct { } } // Simple type: A<T>, etc. abstract class C1<T> : A<T>, I<T> { internal abstract A<U> F<U>(I<U> a); } // Outer type: A<T>.C, etc. abstract class C2<T> : A<T>.C, A<T>.I { internal abstract A<U>.I F<U>(A<U>.C a); } // Inner type: B.C<T>, etc. abstract class C3<T> : B.C<T>, B.I<T> { internal abstract B.C<U> F<U>(B.I<U> a); } // Array: T[]. abstract class C4<T> : A<B.C<T>[]>, I<A<T>[]> { internal abstract I<A<U>[]> F<U>(A<B.C<U>[]> a); } // Generic type parameter: A<I<T>>, etc. abstract class C5<T> : A<I<T>>, I<A<T>> { internal abstract I<A<U>> F<U>(A<I<U>> a); } // Multiple interfaces, multiple method parameters. abstract class C6<T, U> : A<object>, I<object>, B.I<U> { internal abstract void F<X, Y>(I<object> a, A<Y> b); }"; CreateCompilation(source).VerifyDiagnostics( // (13,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C1").WithArguments("A<T>", "T", "T").WithLocation(13, 16), // (13,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C1").WithArguments("I<T>", "T", "T").WithLocation(13, 16), // (15,28): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "F").WithArguments("A<T>", "T", "U").WithLocation(15, 28), // (15,38): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "a").WithArguments("I<T>", "T", "U").WithLocation(15, 38), // (18,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C2").WithArguments("A<T>", "T", "T").WithLocation(18, 16), // (18,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C2").WithArguments("A<T>", "T", "T").WithLocation(18, 16), // (20,30): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "F").WithArguments("A<T>", "T", "U").WithLocation(20, 30), // (20,42): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "a").WithArguments("A<T>", "T", "U").WithLocation(20, 42), // (23,16): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.C<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C3").WithArguments("B.C<U>", "U", "T").WithLocation(23, 16), // (23,16): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.I<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C3").WithArguments("B.I<U>", "U", "T").WithLocation(23, 16), // (25,30): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.C<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "F").WithArguments("B.C<U>", "U", "U").WithLocation(25, 30), // (25,42): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.I<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "a").WithArguments("B.I<U>", "U", "U").WithLocation(25, 42), // (28,16): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.C<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C4").WithArguments("B.C<U>", "U", "T").WithLocation(28, 16), // (28,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C4").WithArguments("A<T>", "T", "T").WithLocation(28, 16), // (30,33): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "F").WithArguments("A<T>", "T", "U").WithLocation(30, 33), // (30,50): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.C<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "a").WithArguments("B.C<U>", "U", "U").WithLocation(30, 50), // (33,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C5").WithArguments("I<T>", "T", "T").WithLocation(33, 16), // (33,16): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "C5").WithArguments("A<T>", "T", "T").WithLocation(33, 16), // (35,31): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "F").WithArguments("A<T>", "T", "U").WithLocation(35, 31), // (35,44): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "a").WithArguments("I<T>", "T", "U").WithLocation(35, 44), // (38,16): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B.I<U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C6").WithArguments("B.I<U>", "U", "U").WithLocation(38, 16), // (40,54): error CS0452: The type 'Y' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "b").WithArguments("A<T>", "T", "Y").WithLocation(40, 54)); } /// <summary> /// Partial method signatures are bound eagerly, not lazily. /// (See SourceMemberMethodSymbol..ctor.) Ensure constraints /// on parameters and return types are checked in those cases. /// </summary> [Fact] public void PartialMethodWithArgumentConstraint() { var source = @"class A<T> where T : struct { internal class B { } } partial class B<T> where T : struct { static partial void M1<U>(A<U> a) where U : struct; static partial void M2<U>(A<U> a, A<A<int>>.B b) where U : class; static partial void M3(A<T> a); static partial void M4<U, V>() where U : A<V>; internal static partial A<U> M5<U>(); } partial class B<T> where T : struct { static partial void M1<U>(A<U> a) where U : struct { } static partial void M2<U>(A<U> a, A<A<int>>.B b) where U : class { } static partial void M3(A<T> a) { } static partial void M4<U, V>() where U : A<V> { } internal static partial A<U> M5<U>() { return null; } }"; CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods).VerifyDiagnostics( // (10,28): error CS0453: The type 'V' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "U").WithArguments("A<T>", "T", "V").WithLocation(10, 28), // (18,28): error CS0453: The type 'V' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "U").WithArguments("A<T>", "T", "V").WithLocation(18, 28), // (8,36): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "a").WithArguments("A<T>", "T", "U").WithLocation(8, 36), // (8,51): error CS0453: The type 'A<int>' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "b").WithArguments("A<T>", "T", "A<int>").WithLocation(8, 51), // (19,34): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M5").WithArguments("A<T>", "T", "U").WithLocation(11, 34)); } [ClrOnlyFact] public void StructAndUnconstrainedTypeParameterConstraints() { var source = @"class C<T, U> where U : struct, T { }"; CompileAndVerify(source); } [ClrOnlyFact] public void WhereTypeParameter() { var source = @"interface I<T> { } class C<where> where where : I<where> { }"; CompileAndVerify(source); } [ClrOnlyFact] public void NewConstraintWithValueType() { var source = @"struct S { } class C<T> where T : new() { static void M(object o) { M(new C<int>()); M(new S()); } }"; CompileAndVerify(source); } [Fact] public void NewConstraintNotInherited() { var source = @"class C<T, U> where T : U where U : new() { static void M(object o) { M(new U()); M(new T()); } }"; CreateCompilation(source).VerifyDiagnostics( // (8,11): error CS0304: Cannot create an instance of the variable type 'T' because it does not have the new() constraint Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T()").WithArguments("T").WithLocation(8, 11)); } [ClrOnlyFact] public void RedundantConstraints() { var source = @"class A { } class B<T> where T : A { class C<U> where U : A, T { class D<V> where V : A, U { } } }"; CompileAndVerify(source); } /// <summary> /// Constraint errors in aliases are reported at the alias declaration, /// and errors are reported regardless of whether the alias is used. /// This is a breaking change from Dev10 which reports constraint errors /// in aliases at the point the alias is used, not at the alias declaration, /// and does not report constraint errors on unused aliases. /// </summary> [Fact] public void AliasConstraintErrors01() { var text = @"using A = C<int>; // unused using B = C<bool>; class C<T> where T : class { static void M() { B.M(); new B(); } }"; CreateCompilation(text).VerifyDiagnostics( // (1,7): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'C<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "A").WithArguments("C<T>", "T", "int").WithLocation(1, 7), // (2,7): error CS0452: The type 'bool' must be a reference type in order to use it as parameter 'T' in the generic type or method 'C<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "B").WithArguments("C<T>", "T", "bool").WithLocation(2, 7), // (1,1): info CS8019: Unnecessary using directive. Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A = C<int>;")); } /// <summary> /// More constraint errors in aliases. /// </summary> [Fact] public void AliasConstraintErrors02() { var text = @"using A = C<I<int?>>; using B1 = C<I<int>>.D1<object>; using B2 = C<int>.D2<string>; interface I<T> where T : struct { } class C<T> where T : class { internal delegate void D1<U>() where U : T; internal delegate void D2<U>() where U : new(); }"; CreateCompilation(text).VerifyDiagnostics( // (1,7): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'I<T>' // using A = C<I<int?>>; Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "A").WithArguments("I<T>", "T", "int?"), // (2,7): error CS0311: The type 'object' cannot be used as type parameter 'U' in the generic type or method 'C<I<int>>.D1<U>'. There is no implicit reference conversion from 'object' to 'I<int>'. // using B1 = C<I<int>>.D1<object>; Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "B1").WithArguments("C<I<int>>.D1<U>", "I<int>", "U", "object"), // (3,7): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'C<T>' // using B2 = C<int>.D2<string>; Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "B2").WithArguments("C<T>", "T", "int"), // (3,7): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'U' in the generic type or method 'C<int>.D2<U>' // using B2 = C<int>.D2<string>; Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "B2").WithArguments("C<int>.D2<U>", "U", "string"), // (1,1): info CS8019: Unnecessary using directive. // using A = C<I<int?>>; Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A = C<I<int?>>;"), // (2,1): info CS8019: Unnecessary using directive. // using B1 = C<I<int>>.D1<object>; Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using B1 = C<I<int>>.D1<object>;"), // (3,1): info CS8019: Unnecessary using directive. // using B2 = C<int>.D2<string>; Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using B2 = C<int>.D2<string>;")); } /// <summary> /// Constraints in method signatures are not checked /// at the time types in the signature are bound. /// Ensure the constraints are checked. /// </summary> [Fact] public void MethodSignatureConstraints() { var text = @"class A : System.Attribute { public A(object o) { } } class B<T> where T : class { } class C { [A(new B<int>())] [return: A(new B<short>())] static B<byte> F( [A(new B<float>())] B<double> o) { return null; } }"; CreateCompilation(text).VerifyDiagnostics( // (11,18): error CS0452: The type 'float' must be a reference type in order to use it as parameter 'T' in the generic type or method 'B<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "float").WithArguments("B<T>", "T", "float").WithLocation(11, 18), // (11,12): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type Diagnostic(ErrorCode.ERR_BadAttributeArgument, "new B<float>()").WithLocation(11, 12), // (10,20): error CS0452: The type 'byte' must be a reference type in order to use it as parameter 'T' in the generic type or method 'B<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "F").WithArguments("B<T>", "T", "byte").WithLocation(10, 20), // (12,19): error CS0452: The type 'double' must be a reference type in order to use it as parameter 'T' in the generic type or method 'B<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "o").WithArguments("B<T>", "T", "double").WithLocation(12, 19), // (8,14): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'B<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("B<T>", "T", "int").WithLocation(8, 14), // (8,8): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type Diagnostic(ErrorCode.ERR_BadAttributeArgument, "new B<int>()").WithLocation(8, 8), // (9,22): error CS0452: The type 'short' must be a reference type in order to use it as parameter 'T' in the generic type or method 'B<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "short").WithArguments("B<T>", "T", "short").WithLocation(9, 22), // (9,16): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type Diagnostic(ErrorCode.ERR_BadAttributeArgument, "new B<short>()").WithLocation(9, 16)); } [Fact] public void DefaultArguments() { var text = @"class A<T> where T : struct { const int F = 1; static void M(int arg = A<object>.F) { } } class B { static int F<T>(int arg = F<string>(0)) where T : struct { return 0; } }"; CreateCompilation(text).VerifyDiagnostics( // (4,31): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "object").WithArguments("A<T>", "T", "object").WithLocation(4, 31), // (8,31): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'B.F<T>(int)' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "F<string>").WithArguments("B.F<T>(int)", "T", "string").WithLocation(8, 31)); } [Fact] public void AttributeReferencingAttributedType() { var text = @"class A : System.Attribute { public A(object o) { } } [A(typeof(C<object>))] class C<T> where T : C<T> { }"; CreateCompilation(text).VerifyDiagnostics( // (5,13): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'C<T>'. There is no implicit reference conversion from 'object' to 'C<object>'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "object").WithArguments("C<T>", "C<object>", "T", "object").WithLocation(5, 13)); } /// <summary> /// Ensure constraint diagnostics are generated. Specifically, /// ensure ForceComplete resolves constraints completely. /// </summary> [Fact] public void ForceComplete() { var source = @"class C<T> where T : A { static void M<U>() where U : B { } } interface IA<T> where T : T { } interface IB { void M<U>() where U : U; }"; CreateCompilation(source).VerifyDiagnostics( // (1,22): error CS0246: The type or namespace name 'A' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "A").WithArguments("A").WithLocation(1, 22), // (3,34): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(3, 34), // (5,14): error CS0454: Circular constraint dependency involving 'T' and 'T' Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(5, 14), // (8, 12): error CS0454: Circular constraint dependency involving 'U' and 'U' Diagnostic(ErrorCode.ERR_CircularConstraint, "U").WithArguments("U", "U").WithLocation(8, 12)); } [Fact] public void ParameterAndReturnTypeViolationsNonMethods01() { var source = @"interface I<T> where T : class { } delegate void D<T>(); class C { C(I<int> i) { } I<byte> P { get; set; } I<double> this[I<float> index] { get { return null; } } event D<I<short>> E; }"; CreateCompilation(source).VerifyDiagnostics( // (8,23): error CS0452: The type 'short' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' // event D<I<short>> E; Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "E").WithArguments("I<T>", "T", "short").WithLocation(8, 23), // (5,14): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' // C(I<int> i) { } Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "i").WithArguments("I<T>", "T", "int").WithLocation(5, 14), // (6,13): error CS0452: The type 'byte' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' // I<byte> P { get; set; } Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "P").WithArguments("I<T>", "T", "byte").WithLocation(6, 13), // (7,29): error CS0452: The type 'float' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' // I<double> this[I<float> index] { get { return null; } } Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "index").WithArguments("I<T>", "T", "float").WithLocation(7, 29), // (7,15): error CS0452: The type 'double' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' // I<double> this[I<float> index] { get { return null; } } Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "this").WithArguments("I<T>", "T", "double").WithLocation(7, 15), // (8,23): warning CS0067: The event 'C.E' is never used // event D<I<short>> E; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("C.E").WithLocation(8, 23)); } [Fact] public void ParameterAndReturnTypeViolationsNonMethods02() { var source = @"interface I<T> where T : class { } class C { static void M() { (delegate(I<long> o) { })(null); ((I<short> o) => { })(); } }"; CreateCompilation(source).VerifyDiagnostics( // (6,21): error CS0452: The type 'long' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "long").WithArguments("I<T>", "T", "long").WithLocation(6, 21), // (6,9): error CS0149: Method name expected Diagnostic(ErrorCode.ERR_MethodNameExpected, "(delegate(I<long> o) { })").WithLocation(6, 9), // (7,13): error CS0452: The type 'short' must be a reference type in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "short").WithArguments("I<T>", "T", "short").WithLocation(7, 13), // (7,9): error CS0149: Method name expected Diagnostic(ErrorCode.ERR_MethodNameExpected, "((I<short> o) => { })").WithLocation(7, 9)); } [Fact] public void FixedFieldArgument() { var source = @"unsafe class C<T> where T : new() { private C() { } fixed int F[C<C<T>>.G]; const int G = 1; }"; CreateCompilation(source, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( // (4,15): error CS1642: Fixed size buffer fields may only be members of structs Diagnostic(ErrorCode.ERR_FixedNotInStruct, "F").WithLocation(4, 15), // (4,19): error CS0310: 'C<T>' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'C<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "C<T>").WithArguments("C<T>", "T", "C<T>").WithLocation(4, 19)); } [ClrOnlyFact] public void PartialClass() { var source = @"interface IA<T> { } interface IB { } partial class C<T> where T : struct, IA<T>, IB { } partial class C<T> where T : struct, IB, IA<T> { } partial class C<T> { }"; CompileAndVerify(source); } [ClrOnlyFact] public void SubstitutedLambdaConstraints() { var source = @"using System; interface I<T> { } class A : I<A> { } class C<T> where T : class, I<T> { static internal Action<T> M() { return (T t) => { }; } } struct S { static internal Action<T> M<T>() where T : class, I<T>, new() { return (T t) => { }; } static void M() { Action<A> a; a = C<A>.M(); a = S.M<A>(); } }"; CompileAndVerify(source); } [WorkItem(528571, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528571")] [Fact] public void ConstraintsWithinStruct() { var source = @"interface I<T> { } struct S { static void M<T>() where T : class, I<T>, new() { } static void N() { S.M<A>(); } class A : I<A> { } }"; CompileAndVerify(source); } [Fact] public void ExtensionMethodsWithConstraints() { var text = @"interface I { } struct S { } static class C { static void M(I i, S s) { i.E(); s.E(); i.F(); s.F(); } static void E(this object o) { } static void E<T>(this T t) where T : new() { } static void F(this object o) { } static void F<T>(this T t) where T : struct { } }"; CreateCompilationWithMscorlib40(text, references: new[] { Net40.References.SystemCore }, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics( // (7,9): error CS0310: 'I' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'C.E<T>(T)' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "i.E").WithArguments("C.E<T>(T)", "T", "I").WithLocation(7, 9), // (9,9): error CS0453: The type 'I' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C.F<T>(T)' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "i.F").WithArguments("C.F<T>(T)", "T", "I").WithLocation(9, 9)); CreateCompilationWithMscorlib40(text, references: new[] { Net40.References.SystemCore }).VerifyDiagnostics(); } [ClrOnlyFact] public void DefaultT() { var source = @"struct S { } class C { static T F1<T>() { return default(T); } static T F2<T>() where T : class { return default(T); } static T F3<T>() where T : struct { return default(T); } static void M(object o) { if (o == null) { o = ""null""; } System.Console.WriteLine(""{0}"", o); } static void Main() { M(F1<C>()); M(F1<S>()); M(F2<C>()); M(F3<S>()); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"null S null S"); var expectedIL = @"{ // Code size 10 (0xa) .maxstack 1 .locals init (T V_0) IL_0000: ldloca.s V_0 IL_0002: initobj ""T"" IL_0008: ldloc.0 IL_0009: ret }"; compilation.VerifyIL("C.F1<T>()", expectedIL); compilation.VerifyIL("C.F2<T>()", expectedIL); compilation.VerifyIL("C.F3<T>()", expectedIL); } [WorkItem(542376, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542376")] [ClrOnlyFact] public void NullT() { var source = @"class C { static object F0() { return null; } static T F1<T>() where T : class { return null; } static T F2<T>() where T : C { return null; } static T F3<T>() where T : class { return (T)null; } static T F4<T>() where T : C { return (T)null; } static T F5<T>() where T : class { return null as T; } static T F6<T>() where T : C { return null as T; } static void M<T>(T t) where T : class { bool b; b = (t == null); b = (t != null); b = (null is T); } }"; var compilation = CompileAndVerify(source); var expectedIL = @"{ // Code size 10 (0xa) .maxstack 1 .locals init (T V_0) IL_0000: ldloca.s V_0 IL_0002: initobj ""T"" IL_0008: ldloc.0 IL_0009: ret }"; compilation.VerifyIL("C.F1<T>()", expectedIL); compilation.VerifyIL("C.F2<T>()", expectedIL); compilation.VerifyIL("C.F3<T>()", expectedIL); compilation.VerifyIL("C.F4<T>()", expectedIL); compilation.VerifyIL("C.F5<T>()", expectedIL); compilation.VerifyIL("C.F6<T>()", expectedIL); } [ClrOnlyFact] public void TryCast() { var source = @"class A { } class B1<T> where T : A { static T F1<U>(U u) { return u as T; } static T F2<U>(U u) where U : A { return u as T; } static T F3<U>(U u) where U : class { return u as T; } static T F4<U>(U u) where U : struct { return u as T; } } class B2<T> where T : class { static T F1<U>(U u) { return u as T; } static T F2<U>(U u) where U : A { return u as T; } static T F3<U>(U u) where U : class { return u as T; } static T F4<U>(U u) where U : struct { return u as T; } }"; var compilation = CompileAndVerify(source); var expectedIL = @"{ // Code size 17 (0x11) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""U"" IL_0006: isinst ""T"" IL_000b: unbox.any ""T"" IL_0010: ret }"; compilation.VerifyIL("B1<T>.F1<U>(U)", expectedIL); compilation.VerifyIL("B1<T>.F2<U>(U)", expectedIL); compilation.VerifyIL("B1<T>.F3<U>(U)", expectedIL); compilation.VerifyIL("B1<T>.F4<U>(U)", expectedIL); compilation.VerifyIL("B2<T>.F1<U>(U)", expectedIL); compilation.VerifyIL("B2<T>.F2<U>(U)", expectedIL); compilation.VerifyIL("B2<T>.F3<U>(U)", expectedIL); compilation.VerifyIL("B2<T>.F4<U>(U)", expectedIL); } [ClrOnlyFact] public void NewT() { var source = @"struct S { } class C { static T F1<T>() where T : new() { return new T(); } static T F2<T>() where T : class, new() { return new T(); } static T F3<T>() where T : struct { return new T(); } static void M(object o) { System.Console.WriteLine(""{0}"", o); } static void Main() { M(F1<C>()); M(F1<S>()); M(F2<C>()); M(F3<S>()); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"C S C S"); compilation.VerifyIL("C.F1<T>()", @" { // Code size 6 (0x6) .maxstack 1 IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: ret }"); compilation.VerifyIL("C.F2<T>()", @"{ // Code size 6 (0x6) .maxstack 1 IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: ret }"); compilation.VerifyIL("C.F3<T>()", @" { // Code size 6 (0x6) .maxstack 1 IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: ret }"); } [WorkItem(542312, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542312")] [ClrOnlyFact] public void NewTStatement() { var source = @"struct S { } class A { } class B { internal B() { } } class C { static void M<T, U, V>() where T : struct where U : new() where V : class, new() { new S(); new A(); new B(); new T(); new U(); new V(); } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.M<T, U, V>()", @" { // Code size 31 (0x1f) .maxstack 1 IL_0000: newobj ""A..ctor()"" IL_0005: pop IL_0006: newobj ""B..ctor()"" IL_000b: pop IL_000c: call ""T System.Activator.CreateInstance<T>()"" IL_0011: pop IL_0012: call ""U System.Activator.CreateInstance<U>()"" IL_0017: pop IL_0018: call ""V System.Activator.CreateInstance<V>()"" IL_001d: pop IL_001e: ret }"); } /// <summary> /// Should bind type parameter constructor arguments /// even though no arguments are expected. /// </summary> [Fact] public void NewTWithBadArguments() { var source = @"struct S<T, U> where T : new() { void M() { object o = new T(F()); o = new U(G()); } }"; CreateCompilation(source).VerifyDiagnostics( // (5,19): error CS0417: 'T': cannot provide arguments when creating an instance of a variable type Diagnostic(ErrorCode.ERR_NewTyvarWithArgs, "new T(F())").WithArguments("T").WithLocation(5, 19), // (5,25): error CS0103: The name 'F' does not exist in the current context Diagnostic(ErrorCode.ERR_NameNotInContext, "F").WithArguments("F").WithLocation(5, 25), // (6,12): error CS0304: Cannot create an instance of the variable type 'U' because it does not have the new() constraint Diagnostic(ErrorCode.ERR_NoNewTyvar, "new U(G())").WithArguments("U").WithLocation(6, 12), // (6,18): error CS0103: The name 'G' does not exist in the current context Diagnostic(ErrorCode.ERR_NameNotInContext, "G").WithArguments("G").WithLocation(6, 18)); } /// <summary> /// Invoke methods and properties on constrained generic types. /// </summary> [ClrOnlyFact] public void Members() { var source = @"using System; interface I { object P { get; set; } void M(); } abstract class A { public abstract object P { get; set; } public abstract void M(); } class B : A, I { public override object P { get { Console.WriteLine(""B.get_P""); return null; } set { Console.WriteLine(""B.set_P""); } } public override void M() { Console.WriteLine(""B.M""); } } struct S : I { public object P { get { Console.WriteLine(""S.get_P""); return null; } set { Console.WriteLine(""S.set_P""); } } public void M() { Console.WriteLine(""S.M""); } } class C<T1, T2> where T1 : I where T2 : A { internal static void M<U1, U2>(T1 t1, T2 t2, U1 u1, U2 u2) where U1 : I where U2 : A { t1.P = t1.P; t1.M(); t2.P = t2.P; t2.M(); u1.P = u1.P; u1.M(); u2.P = u2.P; u2.M(); } } class C { static void Main() { B b = new B(); S s = new S(); C<I, A>.M(s, b, s, b); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"S.get_P S.set_P S.M B.get_P B.set_P B.M S.get_P S.set_P S.M B.get_P B.set_P B.M"); compilation.VerifyIL("C<T1, T2>.M<U1, U2>(T1, T2, U1, U2)", @" { // Code size 193 (0xc1) .maxstack 2 .locals init (T1 V_0, U1 V_1) IL_0000: ldarga.s V_0 IL_0002: ldloca.s V_0 IL_0004: initobj ""T1"" IL_000a: ldloc.0 IL_000b: box ""T1"" IL_0010: brtrue.s IL_001a IL_0012: ldobj ""T1"" IL_0017: stloc.0 IL_0018: ldloca.s V_0 IL_001a: ldarga.s V_0 IL_001c: constrained. ""T1"" IL_0022: callvirt ""object I.P.get"" IL_0027: constrained. ""T1"" IL_002d: callvirt ""void I.P.set"" IL_0032: ldarga.s V_0 IL_0034: constrained. ""T1"" IL_003a: callvirt ""void I.M()"" IL_003f: ldarg.1 IL_0040: box ""T2"" IL_0045: ldarg.1 IL_0046: box ""T2"" IL_004b: callvirt ""object A.P.get"" IL_0050: callvirt ""void A.P.set"" IL_0055: ldarg.1 IL_0056: box ""T2"" IL_005b: callvirt ""void A.M()"" IL_0060: ldarga.s V_2 IL_0062: ldloca.s V_1 IL_0064: initobj ""U1"" IL_006a: ldloc.1 IL_006b: box ""U1"" IL_0070: brtrue.s IL_007a IL_0072: ldobj ""U1"" IL_0077: stloc.1 IL_0078: ldloca.s V_1 IL_007a: ldarga.s V_2 IL_007c: constrained. ""U1"" IL_0082: callvirt ""object I.P.get"" IL_0087: constrained. ""U1"" IL_008d: callvirt ""void I.P.set"" IL_0092: ldarga.s V_2 IL_0094: constrained. ""U1"" IL_009a: callvirt ""void I.M()"" IL_009f: ldarg.3 IL_00a0: box ""U2"" IL_00a5: ldarg.3 IL_00a6: box ""U2"" IL_00ab: callvirt ""object A.P.get"" IL_00b0: callvirt ""void A.P.set"" IL_00b5: ldarg.3 IL_00b6: box ""U2"" IL_00bb: callvirt ""void A.M()"" IL_00c0: ret }"); } [ClrOnlyFact] public void Indexers() { var source = @"using System; interface I { object this[object index] { set; } } class A { internal object this[object index] { get { Console.WriteLine(""A[{0}]"", index); return null; } } } struct S : I { public object this[object index] { set { Console.WriteLine(""S[{0}]"", index); } } } class C { static void M<T, U>(T t, U u) where T : I where U : A { t[0] = u[1]; } static void Main() { M(new S(), new A()); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"A[1] S[0]"); compilation.VerifyIL("C.M<T, U>(T, U)", @" { // Code size 61 (0x3d) .maxstack 4 .locals init (T V_0) IL_0000: ldarga.s V_0 IL_0002: ldloca.s V_0 IL_0004: initobj ""T"" IL_000a: ldloc.0 IL_000b: box ""T"" IL_0010: brtrue.s IL_001a IL_0012: ldobj ""T"" IL_0017: stloc.0 IL_0018: ldloca.s V_0 IL_001a: ldc.i4.0 IL_001b: box ""int"" IL_0020: ldarg.1 IL_0021: box ""U"" IL_0026: ldc.i4.1 IL_0027: box ""int"" IL_002c: callvirt ""object A.this[object].get"" IL_0031: constrained. ""T"" IL_0037: callvirt ""void I.this[object].set"" IL_003c: ret }"); } /// <summary> /// Access fields on constrained generic types. /// </summary> [ClrOnlyFact] [WorkItem(542277, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542277")] public void Fields() { var source = @"class A { internal object F; } class B<T> where T : A { internal static void Swap<U>(T t, U u) where U : T { var v1 = t.F; var v2 = u.F; t.F = v2; u.F = v1; } } class C { static void Main() { var a1 = new A(); var a2 = new A(); a1.F = 1; a2.F = 2; B<A>.Swap(a1, a2); System.Console.WriteLine(""{0}, {1}"", a1.F, a2.F); } }"; var compilation = CompileAndVerify(source, expectedOutput: "2, 1"); compilation.VerifyIL("B<T>.Swap<U>(T, U)", @"{ // Code size 49 (0x31) .maxstack 2 .locals init (object V_0, //v1 object V_1) //v2 IL_0000: ldarg.0 IL_0001: box ""T"" IL_0006: ldfld ""object A.F"" IL_000b: stloc.0 IL_000c: ldarg.1 IL_000d: box ""U"" IL_0012: ldfld ""object A.F"" IL_0017: stloc.1 IL_0018: ldarg.0 IL_0019: box ""T"" IL_001e: ldloc.1 IL_001f: stfld ""object A.F"" IL_0024: ldarg.1 IL_0025: box ""U"" IL_002a: ldloc.0 IL_002b: stfld ""object A.F"" IL_0030: ret }"); } /// <summary> /// Access events on constrained generic types. /// </summary> [ClrOnlyFact] public void Events() { var source = @"delegate void D(); class A { internal event D E; internal static void Swap<T, U>(T t, U u) where T : A where U : T { var v1 = t.E; var v2 = u.E; t.E = v2; u.E = v1; } static void F1() { } static void F2() { } static void Main() { var a1 = new A(); var a2 = new A(); a1.E += F1; a1.E += F2; a2.E += F1; Swap<A, A>(a1, a2); System.Console.WriteLine(""{0}, {1}"", a1.E.GetInvocationList().Length, a2.E.GetInvocationList().Length); } }"; var compilation = CompileAndVerify(source, expectedOutput: "1, 2"); compilation.VerifyIL("A.Swap<T, U>(T, U)", @"{ // Code size 49 (0x31) .maxstack 2 .locals init (D V_0, //v1 D V_1) //v2 IL_0000: ldarg.0 IL_0001: box ""T"" IL_0006: ldfld ""D A.E"" IL_000b: stloc.0 IL_000c: ldarg.1 IL_000d: box ""U"" IL_0012: ldfld ""D A.E"" IL_0017: stloc.1 IL_0018: ldarg.0 IL_0019: box ""T"" IL_001e: ldloc.1 IL_001f: stfld ""D A.E"" IL_0024: ldarg.1 IL_0025: box ""U"" IL_002a: ldloc.0 IL_002b: stfld ""D A.E"" IL_0030: ret }"); } [Fact] public void ConflictingConstraints01() { var source = @"class A { } class B { } class C<S, T, U, V, W> where T : new() where U : struct where V : class where W : A { struct S1<X> where X : S, new() { } struct S2<X> where X : T, new() { } struct S3<X> where X : U, new() { } struct S4<X> where X : V, new() { } struct S5<X> where X : W, new() { } class C1<X> where X : struct, S { } class C2<X> where X : struct, T { } class C3<X> where X : struct, U { } class C4<X> where X : struct, V { } class C5<X> where X : struct, W { } delegate void D1<X>() where X : class, S; delegate void D2<X>() where X : class, T; delegate void D3<X>() where X : class, U; delegate void D4<X>() where X : class, V; delegate void D5<X>() where X : class, W; void M1<X>() where X : A, S { } void M2<X>() where X : A, T { } void M3<X>() where X : A, U { } void M4<X>() where X : A, V { } void M5<X>() where X : A, W { } interface I1<X> where X : B, S { } interface I2<X> where X : B, T { } interface I3<X> where X : B, U { } interface I4<X> where X : B, V { } interface I5<X> where X : B, W { } }"; CreateCompilation(source).VerifyDiagnostics( // (11,15): error CS0456: Type parameter 'U' has the 'struct' constraint so 'U' cannot be used as a constraint for 'X' Diagnostic(ErrorCode.ERR_ConWithValCon, "X").WithArguments("X", "U").WithLocation(11, 15), // (16,14): error CS0456: Type parameter 'U' has the 'struct' constraint so 'U' cannot be used as a constraint for 'X' Diagnostic(ErrorCode.ERR_ConWithValCon, "X").WithArguments("X", "U").WithLocation(16, 14), // (18,14): error CS0455: Type parameter 'X' inherits conflicting constraints 'A' and 'System.ValueType' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "X").WithArguments("X", "A", "System.ValueType").WithLocation(18, 14), // (21,22): error CS0456: Type parameter 'U' has the 'struct' constraint so 'U' cannot be used as a constraint for 'X' Diagnostic(ErrorCode.ERR_ConWithValCon, "X").WithArguments("X", "U").WithLocation(21, 22), // (26,13): error CS0456: Type parameter 'U' has the 'struct' constraint so 'U' cannot be used as a constraint for 'X' Diagnostic(ErrorCode.ERR_ConWithValCon, "X").WithArguments("X", "U").WithLocation(26, 13), // (31,18): error CS0456: Type parameter 'U' has the 'struct' constraint so 'U' cannot be used as a constraint for 'X' Diagnostic(ErrorCode.ERR_ConWithValCon, "X").WithArguments("X", "U").WithLocation(31, 18), // (33,18): error CS0455: Type parameter 'X' inherits conflicting constraints 'A' and 'B' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "X").WithArguments("X", "A", "B").WithLocation(33, 18)); } /// <summary> /// No error for conflicting constraint on virtual method /// in derived class unless the method is overridden. /// </summary> [Fact] public void ConflictingConstraints02() { var source = @"class A { } class B { } class C<T, U> { internal virtual void M<X>() where X : T, U { } } class D1 : C<A, B> { } class D2 : C<A, B> { internal override void M<X>() { } }"; CreateCompilation(source).VerifyDiagnostics( // (10,30): error CS0455: Type parameter 'X' inherits conflicting constraints 'B' and 'A' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "X").WithArguments("X", "B", "A").WithLocation(10, 30)); } [ClrOnlyFact] public void MovedConstraints() { var source = @"interface I { } class C { } interface IA<T, U> where U : T, I { } class A<X> : IA<I, X> where X : I { } class A<X, Y> : IA<X, Y> where X : I where Y : X { } interface IB<T, U> where U : C, T { } class B<X> : IB<C, X> where X : C { } class B<X, Y> : IB<X, Y> where X : C where Y : X { }"; CompileAndVerify(source); } /// <summary> /// The constraint type can be dropped from the overridden /// method if the type is object. Spec. 13.4.3. /// </summary> [Fact] public void OverriddenMethodWithObjectConstraint() { var source = @"interface I<T> { void M1<U>() where U : T; void M2<U>() where U : class, T; } abstract class A<T> { public abstract void M1<U>() where U : T; public void M2<U>() where U : T { } } class B1 : I<object> { public void M1<T>() { } public void M2<T>() { } } class B2 : A<object>, I<object> { public override void M1<T>() { } }"; CreateCompilation(source).VerifyDiagnostics( // (14,17): error CS0425: The constraints for type parameter 'T' of method 'B1.M2<T>()' must match the constraints for type parameter 'U' of interface method 'I<object>.M2<U>()'. Consider using an explicit interface implementation instead. // public void M2<T>() { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M2").WithArguments("T", "B1.M2<T>()", "U", "I<object>.M2<U>()").WithLocation(14, 17), // (16,23): error CS0425: The constraints for type parameter 'U' of method 'A<object>.M2<U>()' must match the constraints for type parameter 'U' of interface method 'I<object>.M2<U>()'. Consider using an explicit interface implementation instead. // class B2 : A<object>, I<object> Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I<object>").WithArguments("U", "A<object>.M2<U>()", "U", "I<object>.M2<U>()").WithLocation(16, 23)); } [Fact] public void ImplicitImplementations() { var source = @"interface I { } class A { } class B : A, I { } interface I1<T, U> { void M<V>() where V : T, U; } class C1<T, U> : I1<T, U> where T : U { public void M<V>() where V : T { } // error } class C2<T> : I1<T, T> { public void M<U>() where U : T { } } class C3 : I1<B, I> { public void M<T>() where T : B, I { } } class C4 : I1<B, I> { public void M<T>() where T : B { } // error } class C5 : I1<A, A> { public void M<T>() where T : A { } } class C6 : I1<A, B> { public void M<T>() where T : B { } // error } interface I2<T> { void M<U>() where U : class, T, I; } class C7<T> : I2<T> where T : I { public void M<U>() where U : class, T { } // error } class C8 : I2<A> { public void M<T>() where T : A, I { } // error } class C9 : I2<B> { public void M<T>() where T : B { } // error } interface I3<T> { void M<U>() where U : struct, T, I; } class C10 : I3<I> { public void M<U>() where U : struct, I { } }"; CreateCompilation(source).VerifyDiagnostics( // (10,17): error CS0425: The constraints for type parameter 'V' of method 'C1<T, U>.M<V>()' must match the constraints for type parameter 'V' of interface method 'I1<T, U>.M<V>()'. Consider using an explicit interface implementation instead. Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("V", "C1<T, U>.M<V>()", "V", "I1<T, U>.M<V>()").WithLocation(10, 17), // (22,17): error CS0425: The constraints for type parameter 'T' of method 'C4.M<T>()' must match the constraints for type parameter 'V' of interface method 'I1<B, I>.M<V>()'. Consider using an explicit interface implementation instead. Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C4.M<T>()", "V", "I1<B, I>.M<V>()").WithLocation(22, 17), // (30,17): error CS0425: The constraints for type parameter 'T' of method 'C6.M<T>()' must match the constraints for type parameter 'V' of interface method 'I1<A, B>.M<V>()'. Consider using an explicit interface implementation instead. Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C6.M<T>()", "V", "I1<A, B>.M<V>()").WithLocation(30, 17), // (38,17): error CS0425: The constraints for type parameter 'U' of method 'C7<T>.M<U>()' must match the constraints for type parameter 'U' of interface method 'I2<T>.M<U>()'. Consider using an explicit interface implementation instead. Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("U", "C7<T>.M<U>()", "U", "I2<T>.M<U>()").WithLocation(38, 17), // (42,17): error CS0425: The constraints for type parameter 'T' of method 'C8.M<T>()' must match the constraints for type parameter 'U' of interface method 'I2<A>.M<U>()'. Consider using an explicit interface implementation instead. Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C8.M<T>()", "U", "I2<A>.M<U>()").WithLocation(42, 17), // (46,17): error CS0425: The constraints for type parameter 'T' of method 'C9.M<T>()' must match the constraints for type parameter 'U' of interface method 'I2<B>.M<U>()'. Consider using an explicit interface implementation instead. Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C9.M<T>()", "U", "I2<B>.M<U>()").WithLocation(46, 17)); } /// <summary> /// Report ERR_ImplBadConstraints on the base class that /// implements the interface methods with incorrect constraints, /// even when the base class does not implement the interface. /// </summary> [Fact] public void CS0425ERR_ImplBadConstraints_BaseFromSource() { var source = @"interface I { void M<T>() where T : class; } class A1 { public void M<T>() where T : class { } } class B1 : A1, I { } class A2 { public void M<T>() where T : struct { } } class B2 : A2, I { } class A3 { public void M<T>() { } } class B3 : A3, I { } class A4 : I { public void M<T>() { } } class B4 : A4, I { }"; CreateCompilation(source).VerifyDiagnostics( // (16,16): error CS0425: The constraints for type parameter 'T' of method 'A2.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class B2 : A2, I Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A2.M<T>()", "T", "I.M<T>()").WithLocation(16, 16), // (23,16): error CS0425: The constraints for type parameter 'T' of method 'A3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class B3 : A3, I Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A3.M<T>()", "T", "I.M<T>()").WithLocation(23, 16), // (28,17): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // public void M<T>() { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(28, 17), // (30,16): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class B4 : A4, I Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(30, 16)); } /// <summary> /// Same as CS0425ERR_ImplBadConstraints_BaseFromSource /// but with base class defined in metadata. /// </summary> [Fact] public void CS0425ERR_ImplBadConstraints_BaseFromMetadata() { var ilSource = @".class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<class T>() { } } .class public A1 { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<class T>() { ret } } .class public A2 { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<valuetype T>() { ret } } .class public A3 { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<T>() { ret } } .class public A4 implements I { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<T>() { ret } } .class public A5 { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<T, U>() { ret } }"; var csharpSource = @"class B1 : A1, I { } class B2 : A2, I { } class B3 : A3, I { } class B4 : A4, I { } class B5 : A5, I { }"; CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics( // (2,16): error CS0425: The constraints for type parameter 'T' of method 'A2.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class B2 : A2, I { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A2.M<T>()", "T", "I.M<T>()").WithLocation(2, 16), // (3,16): error CS0425: The constraints for type parameter 'T' of method 'A3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class B3 : A3, I { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A3.M<T>()", "T", "I.M<T>()").WithLocation(3, 16), // (4,16): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class B4 : A4, I { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(4, 16), // (5,16): error CS0535: 'B5' does not implement interface member 'I.M<T>()' // class B5 : A5, I { } Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("B5", "I.M<T>()").WithLocation(5, 16)); } /// <summary> /// Should not report constraint differences across partial declarations /// if the only differences are duplicated constraints. /// </summary> [Fact] public void DuplicateConstraintDifferencesOnPartialDeclarations() { var source = @"interface IA { } // Differ only by duplicates. partial class A<T> where T : IA, IA { } partial class A<T> where T : IA { } partial class A<T> where T : IA, IA { } // Differ by duplicates and others. partial class B<T, U> where T : IA, IA { } partial class B<T, U> where T : U, IA { } class C<T> { // Differ only by duplicates. interface IB<U> { } partial class B<U, V> where U : T, T where V : U, IB<T> { } partial class B<U, V> where U : T where V : U, U, IB<T>, IB<T> { } }"; CreateCompilation(source).VerifyDiagnostics( // (3,34): error CS0405: Duplicate constraint 'IA' for type parameter 'T' Diagnostic(ErrorCode.ERR_DuplicateBound, "IA").WithArguments("IA", "T").WithLocation(3, 34), // (5,34): error CS0405: Duplicate constraint 'IA' for type parameter 'T' Diagnostic(ErrorCode.ERR_DuplicateBound, "IA").WithArguments("IA", "T").WithLocation(5, 34), // (7,15): error CS0265: Partial declarations of 'B<T, U>' have inconsistent constraints for type parameter 'T' Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "B").WithArguments("B<T, U>", "T").WithLocation(7, 15), // (7,37): error CS0405: Duplicate constraint 'IA' for type parameter 'T' Diagnostic(ErrorCode.ERR_DuplicateBound, "IA").WithArguments("IA", "T").WithLocation(7, 37), // (13,40): error CS0405: Duplicate constraint 'T' for type parameter 'U' Diagnostic(ErrorCode.ERR_DuplicateBound, "T").WithArguments("T", "U").WithLocation(13, 40), // (14,52): error CS0405: Duplicate constraint 'U' for type parameter 'V' Diagnostic(ErrorCode.ERR_DuplicateBound, "U").WithArguments("U", "V").WithLocation(14, 52), // (14,62): error CS0405: Duplicate constraint 'C<T>.IB<T>' for type parameter 'V' Diagnostic(ErrorCode.ERR_DuplicateBound, "IB<T>").WithArguments("C<T>.IB<T>", "V").WithLocation(14, 62)); } [Fact] public void DuplicateConstraintDifferencesOnPartialMethod() { var source = @"interface I<T> { } partial class C<T> { partial void F<U>() where U : T, T, I<T>; partial void F<U>() where U : T, I<T>, I<T> { } }"; CreateCompilation(source).VerifyDiagnostics( // (4,38): error CS0405: Duplicate constraint 'T' for type parameter 'U' // partial void F<U>() where U : T, T, I<T>; Diagnostic(ErrorCode.ERR_DuplicateBound, "T").WithArguments("T", "U").WithLocation(4, 38), // (5,44): error CS0405: Duplicate constraint 'I<T>' for type parameter 'U' // partial void F<U>() where U : T, I<T>, I<T> { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I<T>").WithArguments("I<T>", "U").WithLocation(5, 44)); } [Fact] public void ConstraintErrorMultiplePartialDeclarations_01() { var source = @"interface I { } class A { } sealed class B { } static class S { } partial class C<T> where T : S { } partial class C<T> where T : S { } partial class D<T> where T : A, I { } partial class D<T> where T : I, A { } partial class D<T> where T : I, A { } partial class E<T> where T : B { } partial class E<T> where T : I, B { } "; CreateCompilation(source).VerifyDiagnostics( // (5,30): error CS0717: 'S': static classes cannot be used as constraints // partial class C<T> where T : S { } Diagnostic(ErrorCode.ERR_ConstraintIsStaticClass, "S").WithArguments("S").WithLocation(5, 30), // (6,30): error CS0717: 'S': static classes cannot be used as constraints // partial class C<T> where T : S { } Diagnostic(ErrorCode.ERR_ConstraintIsStaticClass, "S").WithArguments("S").WithLocation(6, 30), // (7,15): error CS0265: Partial declarations of 'D<T>' have inconsistent constraints for type parameter 'T' // partial class D<T> where T : A, I { } Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "D").WithArguments("D<T>", "T").WithLocation(7, 15), // (8,33): error CS0406: The class type constraint 'A' must come before any other constraints // partial class D<T> where T : I, A { } Diagnostic(ErrorCode.ERR_ClassBoundNotFirst, "A").WithArguments("A").WithLocation(8, 33), // (9,33): error CS0406: The class type constraint 'A' must come before any other constraints // partial class D<T> where T : I, A { } Diagnostic(ErrorCode.ERR_ClassBoundNotFirst, "A").WithArguments("A").WithLocation(9, 33), // (10,15): error CS0265: Partial declarations of 'E<T>' have inconsistent constraints for type parameter 'T' // partial class E<T> where T : B { } Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "E").WithArguments("E<T>", "T").WithLocation(10, 15), // (10,30): error CS0701: 'B' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // partial class E<T> where T : B { } Diagnostic(ErrorCode.ERR_BadBoundType, "B").WithArguments("B").WithLocation(10, 30), // (11,33): error CS0701: 'B' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // partial class E<T> where T : I, B { } Diagnostic(ErrorCode.ERR_BadBoundType, "B").WithArguments("B").WithLocation(11, 33)); } [Fact] public void ConstraintErrorMultiplePartialDeclarations_02() { var source = @"sealed class A { } partial class B<T, U> where T : A where U : T { } partial class B<T, U> where T : A { } partial class C<T, U> where U : T { } partial class C<T, U> where T : A where U : T { } "; CreateCompilation(source).VerifyDiagnostics( // (2,15): error CS0265: Partial declarations of 'B<T, U>' have inconsistent constraints for type parameter 'U' // partial class B<T, U> where T : A where U : T { } Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "B").WithArguments("B<T, U>", "U").WithLocation(2, 15), // (2,33): error CS0701: 'A' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // partial class B<T, U> where T : A where U : T { } Diagnostic(ErrorCode.ERR_BadBoundType, "A").WithArguments("A").WithLocation(2, 33), // (3,33): error CS0701: 'A' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // partial class B<T, U> where T : A { } Diagnostic(ErrorCode.ERR_BadBoundType, "A").WithArguments("A").WithLocation(3, 33), // (5,33): error CS0701: 'A' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // partial class C<T, U> where T : A where U : T { } Diagnostic(ErrorCode.ERR_BadBoundType, "A").WithArguments("A").WithLocation(5, 33)); } [Fact] public void EffectiveBaseClass01() { var source = @"class A { internal object F; } class B : A { internal object G; } class C : B { internal object H; } class D<T> where T : B { static void M<X, Y, Z>(X x, Y y, Z z) where X : A, T where Y : C, T where Z : C, X { object o; o = x.F; o = x.G; o = x.H; o = y.F; o = y.G; o = y.H; o = z.F; o = z.G; o = z.H; } }"; CreateCompilation(source).VerifyDiagnostics( // (23,15): error CS1061: 'X' does not contain a definition for 'H' and no extension method 'H' accepting a first argument of type 'X' could be found (are you missing a using directive or an assembly reference?) // o = x.H; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "H").WithArguments("X", "H"), // (3,21): warning CS0649: Field 'A.F' is never assigned to, and will always have its default value null // internal object F; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("A.F", "null"), // (7,21): warning CS0649: Field 'B.G' is never assigned to, and will always have its default value null // internal object G; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "G").WithArguments("B.G", "null"), // (11,21): warning CS0649: Field 'C.H' is never assigned to, and will always have its default value null // internal object H; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "H").WithArguments("C.H", "null") ); } [Fact] public void EffectiveBaseClass02() { var source = @"struct S { } class A<T> { public virtual void F<U>(U u) where U : T { } public void M(T t) { } } class B1 : A<int> { public override void F<U>(U u) { int i = u; M(u); } } class B2 : A<S> { public override void F<U>(U u) { S s = u; M(u); } }"; CreateCompilation(source).VerifyDiagnostics( // (11,17): error CS0029: Cannot implicitly convert type 'U' to 'int' Diagnostic(ErrorCode.ERR_NoImplicitConv, "u").WithArguments("U", "int").WithLocation(11, 17), // (12,11): error CS1503: Argument 1: cannot convert from 'U' to 'int' Diagnostic(ErrorCode.ERR_BadArgType, "u").WithArguments("1", "U", "int").WithLocation(12, 11), // (19,15): error CS0029: Cannot implicitly convert type 'U' to 'S' Diagnostic(ErrorCode.ERR_NoImplicitConv, "u").WithArguments("U", "S").WithLocation(19, 15), // (20,11): error CS1503: Argument 1: cannot convert from 'U' to 'S' Diagnostic(ErrorCode.ERR_BadArgType, "u").WithArguments("1", "U", "S").WithLocation(20, 11)); } /// <summary> /// Should not be able to access members on constraint /// type if type is a struct (since effective base class /// should be nearest reference type in type hierarchy). /// </summary> [Fact] public void EffectiveBaseClass03() { var source = @"struct S { internal object F; } class C { internal object F; } abstract class A<T1, T2> { internal abstract void M<U1, U2>(U1 u1, U2 u2) where U1 : T1 where U2 : T2; } class B : A<S, C> { internal override void M<U1, U2>(U1 u1, U2 u2) { u1.F = u2.F; } }"; CreateCompilation(source).VerifyDiagnostics( // (17,12): error CS1061: 'U1' does not contain a definition for 'F' and no extension method 'F' accepting a first argument of type 'U1' could be found (are you missing a using directive or an assembly reference?) // u1.F = u2.F; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F").WithArguments("U1", "F"), // (3,21): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value null // internal object F; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "null"), // (7,21): warning CS0649: Field 'C.F' is never assigned to, and will always have its default value null // internal object F; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "null") ); } /// <summary> /// Should not be able to access protected /// members on constraint type. /// </summary> [Fact] public void EffectiveBaseClass04() { var source = @"class A { protected void M() { } } class B { } class C<T, U> where T : A where U : B { static void M(T t, U u) { t.M(); u.M(); } }"; CreateCompilation(source).VerifyDiagnostics( // (14,11): error CS0122: 'A.M()' is inaccessible due to its protection level Diagnostic(ErrorCode.ERR_BadAccess, "M").WithArguments("A.M()").WithLocation(14, 11), // (15,11): error CS1061: 'U' does not contain a definition for 'M' and no extension method 'M' accepting a first argument of type 'U' could be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("U", "M").WithLocation(15, 11)); } [Fact] public void EffectiveInterfaceSet01() { var source = @"using System.Collections.Generic; abstract class A<T> { internal abstract void M<U>(T t, U u) where U : T; internal static void M_Array(object[] o) { } internal static void M_IList(IList<object> o) { } } class B : A<object[]> { internal override void M<U>(object[] t, U u) { M_Array(t); M_Array(u); M_IList(t); M_IList(u); } }"; CreateCompilation(source).VerifyDiagnostics( // (13,17): error CS1503: Argument 1: Argument 1: cannot convert from 'U' to 'object[]' Diagnostic(ErrorCode.ERR_BadArgType, "u").WithArguments("1", "U", "object[]").WithLocation(13, 17), // (15,17): error CS1503: Argument 1: Argument 1: cannot convert from 'U' to 'System.Collections.Generic.IList<object>' Diagnostic(ErrorCode.ERR_BadArgType, "u").WithArguments("1", "U", "System.Collections.Generic.IList<object>").WithLocation(15, 17)); } /// <summary> /// Explicit interface implementations on class constraints /// should not be included in member lookup. /// </summary> [Fact] public void EffectiveInterfaceSet02() { var source = @"interface I { void M(); } class A : I { void I.M() { } } class B : I { public void M() { } } class C { static void M<T1, T2, T3, T4, T5>(A a, B b, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) where T1 : A where T2 : A, I where T3 : B where T4 : T1 where T5 : T1, I { a.M(); b.M(); t1.M(); t2.M(); t3.M(); t4.M(); t5.M(); } }"; CreateCompilation(source).VerifyDiagnostics( // (22,11): error CS1061: 'A' does not contain a definition for 'M' and no extension method 'M' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("A", "M").WithLocation(22, 11), // (24,12): error CS1061: 'T1' does not contain a definition for 'M' and no extension method 'M' accepting a first argument of type 'T1' could be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("T1", "M").WithLocation(24, 12), // (27,12): error CS1061: 'T4' does not contain a definition for 'M' and no extension method 'M' accepting a first argument of type 'U1' could be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("T4", "M").WithLocation(27, 12)); } /// <summary> /// Class constraint members should hide /// interface constraint members. /// </summary> [ClrOnlyFact] public void EffectiveInterfaceSet03() { var source = @"interface I { void M(); } class A { internal void M() { System.Console.WriteLine(""A.M""); } } class B : A, I { void I.M() { System.Console.WriteLine(""B.M""); } } class C { static void M<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) where T1 : I where T2 : A where T3 : A, I where T4 : A, T1 where T5 : T2, I where T6 : T1, T2 { t1.M(); t2.M(); t3.M(); t4.M(); t5.M(); t6.M(); } static void Main() { var b = new B(); M(b, b, b, b, b, b); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"B.M A.M A.M A.M A.M A.M"); } /// <summary> /// Method type inference should consider all /// interfaces reachable from the type parameter. /// </summary> [Fact] public void EffectiveInterfaceSet04() { var source = @"interface IA<T> { } interface IB<T> : IA<T> { } class A : IA<object> { } class C { static void M<T>(IA<T> t) { } static void M<T, U>(T t, U u) where T : A where U : IB<object> { M(t); M(u); } }"; CreateCompilation(source).VerifyDiagnostics(); } [ClrOnlyFact] public void ThrowT() { var source = @"class C<T> where T : System.Exception { static void ThrowT<U>() where U : T, new() { throw new U(); } static void ThrowT(T t) { throw t; } static void RethrowT() { try { } catch (T) { throw; } } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C<T>.ThrowT(T)", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""T"" IL_0006: throw }"); } [ClrOnlyFact] public void CatchT() { var source = @"class C<T> where T : System.Exception { static void M<U>() where U : T { try { } catch (T) { } try { } catch (U) { } } }"; CompileAndVerify(source); } [ClrOnlyFact] public void CatchTLifted() { var source = @" class C<T> where T : System.Exception { public static void M<U>() where U : T { System.Action a = () => { try { throw new System.ArgumentException(); } catch (T e) { System.Action aa = () => System.Console.WriteLine(e.ToString()); aa(); } try { throw new System.ArgumentException(); } catch (U e) { System.Action aa = () => System.Console.WriteLine(e.ToString()); aa(); } }; a(); } } class Test { static void Main() { C<System.Exception>.M<System.ArgumentException>(); } }"; CompileAndVerify(source); } [Fact] public void OverriddenConstraintTypes() { var source = @"class A<T> { internal virtual void M<U>() where U : T { } } // U as class type. class B1 : A<object> { internal override void M<U>() { } } // U as value type. class B2 : A<int> { internal override void M<U>() { } } // U as nullable type. class B3 : A<int?> { internal override void M<U>() { } } // U as enum type. enum E { } class B4 : A<E> { internal override void M<U>() { } } // U as delegate type. delegate void D(); class B5 : A<D> { internal override void M<U>() { } } // U as array type. class B6 : A<object[]> { internal override void M<U>() { } } // U as interface type. interface I { } class B7 : A<I> { internal override void M<U>() { } } // U as dynamic type. class B8 : A<dynamic> { internal override void M<U>() { } } // U as error type. class B9 : A<Unknown> { internal override void M<U>() { } }"; CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics( // (49,14): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(49, 14)); } [Fact] public void ErrorTypesInConstraints() { var source = @"class A { } // U depends on T where T has an error type. class B<T, U> where T : X where U : I<T> { } // T depends on a valid type and an error type. class C<T> where T : A, Y { // U depends on an error type and a valid type. void M<U>() where U : Z, A { } }"; CreateCompilation(source).VerifyDiagnostics( // (10,18): error CS0246: The type or namespace name 'Y' could not be found (are you missing a using directive or an assembly reference?) // where T : A, Y Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Y").WithArguments("Y").WithLocation(10, 18), // (4,15): error CS0246: The type or namespace name 'X' could not be found (are you missing a using directive or an assembly reference?) // where T : X Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "X").WithArguments("X").WithLocation(4, 15), // (5,15): error CS0246: The type or namespace name 'I<>' could not be found (are you missing a using directive or an assembly reference?) // where U : I<T> Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I<T>").WithArguments("I<>").WithLocation(5, 15), // (13,27): error CS0246: The type or namespace name 'Z' could not be found (are you missing a using directive or an assembly reference?) // void M<U>() where U : Z, A { } Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Z").WithArguments("Z").WithLocation(13, 27), // (13,30): error CS0406: The class type constraint 'A' must come before any other constraints // void M<U>() where U : Z, A { } Diagnostic(ErrorCode.ERR_ClassBoundNotFirst, "A").WithArguments("A").WithLocation(13, 30)); } [ClrOnlyFact] public void LookupObjectMembers() { var source = @"interface IA { } interface IB { } class C<T> where T : IA, IB { static string F<U>(T t, U u) where U : T { return t.ToString() + u.GetHashCode(); } static string G<U, V>(U u, V v) where V : struct { return u.ToString() + v.GetHashCode(); } }"; CompileAndVerify(source); } /// <summary> /// Handle constraints from metadata that /// would be invalid from source. /// </summary> [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void InvalidConstraintsFromMetadata() { var ilSource = @".class public sealed Sealed { } .class public abstract sealed Static { } .class enum public Enum extends [mscorlib]System.Enum { .field public int32 value__; } .class value public Struct extends [mscorlib]System.ValueType { } .class public C1<([mscorlib]System.Object)T> { .field public static object F; } .class public C2<([mscorlib]System.Enum)T> { .field public static object F; } .class public C3<([mscorlib]System.ValueType)T> { .field public static object F; } .class public C4<([mscorlib]System.Array)T> { .field public static object F; } .class public C5<([mscorlib]System.Int32)T> { .field public static object F; } .class public C6<(Sealed)T> { .field public static object F; } .class public C7<(Static)T> { .field public static object F; } .class public C8<(Enum)T> { .field public static object F; } .class public C9<(Struct)T> { .field public static object F; }"; var csharpSource = @"class C { static void M() { object o; // C1<T> where T : object o = C1<object>.F; o = C1<string>.F; // C2<T> where T : enum o = C2<Enum>.F; o = C2<string>.F; // C3<T> where T : System.ValueType o = C3<int>.F; o = C3<string>.F; // C4<T> where T : System.Array o = C4<object[]>.F; o = C4<string>.F; // C5<T> where T : int o = C5<int>.F; o = C5<string>.F; // C6<T> where T : sealed-type o = C6<Sealed>.F; o = C6<string>.F; // C7<T> where T : static-type o = C7<Static>.F; o = C7<string>.F; // C8<T> where T : enum-type o = C8<Enum>.F; o = C8<string>.F; // C9<T> where T : struct-type o = C9<Struct>.F; o = C9<string>.F; } }"; CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics( // (11,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C2<T>'. There is no implicit reference conversion from 'string' to 'System.Enum'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C2<T>", "System.Enum", "T", "string").WithLocation(11, 16), // (14,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C3<T>'. There is no implicit reference conversion from 'string' to 'System.ValueType'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C3<T>", "System.ValueType", "T", "string").WithLocation(14, 16), // (17,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C4<T>'. There is no implicit reference conversion from 'string' to 'System.Array'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C4<T>", "System.Array", "T", "string").WithLocation(17, 16), // (20,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C5<T>'. There is no implicit reference conversion from 'string' to 'int'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C5<T>", "int", "T", "string").WithLocation(20, 16), // (23,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C6<T>'. There is no implicit reference conversion from 'string' to 'Sealed'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C6<T>", "Sealed", "T", "string").WithLocation(23, 16), // (25,16): error CS0718: 'Static': static types cannot be used as type arguments Diagnostic(ErrorCode.ERR_GenericArgIsStaticClass, "Static").WithArguments("Static").WithLocation(25, 16), // (26,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C7<T>'. There is no implicit reference conversion from 'string' to 'Static'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C7<T>", "Static", "T", "string").WithLocation(26, 16), // (29,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C8<T>'. There is no implicit reference conversion from 'string' to 'Enum'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C8<T>", "Enum", "T", "string").WithLocation(29, 16), // (32,16): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'C9<T>'. There is no implicit reference conversion from 'string' to 'Struct'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("C9<T>", "Struct", "T", "string").WithLocation(32, 16)); } /// <summary> /// Use-site errors should be reported when a type or /// method from PE with a circular constraint is used. /// </summary> [Fact] public void UseSiteErrorCircularConstraints() { var ilSource = @".class public A<(!T)T> { } .class public B { .method public static void M<(!!U)T, (!!T)U>() { ret } }"; var csharpSource = @"class C { static void M(A<object> a) { } static void M() { B.M<string, string>(); } }"; CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics( // (3,29): error CS0454: Circular constraint dependency involving 'T' and 'T' // static void M(A<object> a) { } Diagnostic(ErrorCode.ERR_CircularConstraint, "a").WithArguments("T", "T").WithLocation(3, 29), // (6,11): error CS0454: Circular constraint dependency involving 'T' and 'U' // B.M<string, string>(); Diagnostic(ErrorCode.ERR_CircularConstraint, "M<string, string>").WithArguments("T", "U").WithLocation(6, 11)); } /// <summary> /// Use-site errors should not be reported for a type or /// method from PE with a missing constraint type in /// addition to any conversion error satisfying constraints. /// </summary> [Fact] public void UseSiteErrorMissingConstraintType() { var ilSource = @".assembly extern other {} .class public A<([other]C)T> { } .class public B { .method public static void M<([other]C)U>() { ret } }"; var csharpSource = @"class D { static void M(A<object> a) { } static void M() { B.M<string>(); } }"; // Note: for method overload resolution, methods with use-site errors // are ignored so there is no constraint error for B.M<string>(). CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics( // (3,29): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A<T>'. There is no implicit reference conversion from 'object' to 'C'. // static void M(A<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A<T>", "C", "T", "object").WithLocation(3, 29), // (3,29): error CS0012: The type 'C' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("C", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(3, 29), // (6,11): error CS0311: The type 'string' cannot be used as type parameter 'U' in the generic type or method 'B.M<U>()'. There is no implicit reference conversion from 'string' to 'C'. // B.M<string>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<string>").WithArguments("B.M<U>()", "C", "U", "string").WithLocation(6, 11), // (6,11): error CS0012: The type 'C' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // B.M<string>(); Diagnostic(ErrorCode.ERR_NoTypeDef, "M<string>").WithArguments("C", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(6, 11)); } [Fact] public void UseSiteErrorMissingConstraintTypeOverriddenMethod() { var source1 = @"public interface IA { } public class A { }"; var compilation1 = CreateCompilation(source1, assemblyName: "d521fe98-c881-45cf-0788-249e00d004ea"); compilation1.VerifyDiagnostics(); var source2 = @"public interface IB : IA { } public class B : A { } public interface IB<T> { } public class B<T> { } public interface IB1 { void M1<T, U>() where T : IA where U : B; } public interface IB2 { void M2<T, U>() where T : IB where U : A; } public interface IB3 { void M3<T, U>() where T : B<IA> where U : T, IB<A[]>; } public interface IB4<T, U> { void M4<V, W>() where V : T where W : U; } public interface IB5 : IB4<A, IA> { } public abstract class B1 { public abstract void M1<T, U>() where T : IA where U : B; } public abstract class B2 { public abstract void M2<T, U>() where T : IB where U : A; } public abstract class B3 { public abstract void M3<T, U>() where T : B<IA> where U : T, IB<A[]>; } public abstract class B4<T, U> { public abstract void M4<V, W>() where V : T where W : U; } public abstract class B5 : B4<A, IA> { }"; var compilation2 = CreateCompilation(source2, references: new MetadataReference[] { MetadataReference.CreateFromImage(compilation1.EmitToArray()) }); compilation2.VerifyDiagnostics(); var source3 = @"class C1A : IB1 { void IB1.M1<T1A, U1A>() { } } class C2A : IB2 { void IB2.M2<T2A, U2A>() { } } class C3A : IB3 { void IB3.M3<T3A, U3A>() { } } class C1B : B1 { public override void M1<T1B, U1B>() { } } class C2B : B2 { public override void M2<T2B, U2B>() { } } class C3B : B3 { public override void M3<T3B, U3B>() { } } class C5B : B5 { public override void M4<T4B, U4B>() { } }"; var compilation3 = CreateCompilation(source3, references: new MetadataReference[] { MetadataReference.CreateFromImage(compilation2.EmitToArray()) }); compilation3.VerifyDiagnostics( // (3,17): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // void IB1.M1<T1A, U1A>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "T1A").WithArguments("IA", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(3, 17), // (7,22): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // void IB2.M2<T2A, U2A>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "U2A").WithArguments("A", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 22), // (11,17): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // void IB3.M3<T3A, U3A>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "T3A").WithArguments("IA", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 17), // (11,22): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // void IB3.M3<T3A, U3A>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "U3A").WithArguments("A", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 22), // (15,29): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // public override void M1<T1B, U1B>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "T1B").WithArguments("IA", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(15, 29), // (19,34): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // public override void M2<T2B, U2B>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "U2B").WithArguments("A", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(19, 34), // (23,29): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // public override void M3<T3B, U3B>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "T3B").WithArguments("IA", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(23, 29), // (23,34): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // public override void M3<T3B, U3B>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "U3B").WithArguments("A", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(23, 34), // (25,13): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // class C5B : B5 Diagnostic(ErrorCode.ERR_NoTypeDef, "B5").WithArguments("A", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(25, 13), // (27,29): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // public override void M4<T4B, U4B>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "T4B").WithArguments("A", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(27, 29), // (27,34): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // public override void M4<T4B, U4B>() { } Diagnostic(ErrorCode.ERR_NoTypeDef, "U4B").WithArguments("IA", "d521fe98-c881-45cf-0788-249e00d004ea, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(27, 34)); } /// <summary> /// If a type parameter from metadata has multiple errors /// including a missing constraint type (a use-site error on /// the constraint type), the missing constraint type should /// be reported as the use-site error for the type parameter. /// </summary> [Fact] public void UseSiteErrorMissingConstraintTypeAndCircularConstraint() { var ilSource = @".assembly extern other {} .class public A1<([other]B1, !T)T> { } .class public A2<([other]B2, [other]I)T> { } .class public A3 { .method static public hidebysig void M<([other]B3, !!T)T>() { ret } }"; var csharpSource = @"class C { static void M(A1<object> a) { } static void M(A2<object> a) { } static void M() { A3.M<object>(); } }"; CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics( // (4,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A2<T>'. There is no implicit reference conversion from 'object' to 'B2'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A2<T>", "B2", "T", "object").WithLocation(4, 30), // (4,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A2<T>'. There is no implicit reference conversion from 'object' to 'I'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A2<T>", "I", "T", "object").WithLocation(4, 30), // (4,30): error CS0012: The type 'B2' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("B2", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(4, 30), // (4,30): error CS0012: The type 'I' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("I", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(4, 30), // (3,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A1<T>'. There is no implicit reference conversion from 'object' to 'B1'. // static void M(A1<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A1<T>", "B1", "T", "object").WithLocation(3, 30), // (3,30): error CS0454: Circular constraint dependency involving 'T' and 'T' // static void M(A1<object> a) { } Diagnostic(ErrorCode.ERR_CircularConstraint, "a").WithArguments("T", "T").WithLocation(3, 30), // (3,30): error CS0012: The type 'B1' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A1<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("B1", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(3, 30), // (7,12): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A3.M<T>()'. There is no implicit reference conversion from 'object' to 'B3'. // A3.M<object>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<object>").WithArguments("A3.M<T>()", "B3", "T", "object").WithLocation(7, 12), // (7,12): error CS0454: Circular constraint dependency involving 'T' and 'T' // A3.M<object>(); Diagnostic(ErrorCode.ERR_CircularConstraint, "M<object>").WithArguments("T", "T").WithLocation(7, 12), // (7,12): error CS0012: The type 'B3' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // A3.M<object>(); Diagnostic(ErrorCode.ERR_NoTypeDef, "M<object>").WithArguments("B3", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 12)); } // Same as UseSiteErrorMissingConstraintTypeAndCircularConstraint but // with use-site errors from retargeting symbols rather than PE symbols. [Fact] public void RetargetingUseSiteErrorMissingConstraintTypeAndCircularConstraint() { var source1 = @"public class B1 { } public class B2 { } public class B3 { } public interface I { }"; var compilation1 = CreateCompilation(source1, assemblyName: "d521fe98-c881-45cf-8870-249e00ae400d"); compilation1.VerifyDiagnostics(); var source2 = @"public class A1<T> where T : B1, T { } public class A2<T> where T : B2, I { } public class A3 { public static void M<T>() where T : B3, T { } }"; var compilation2 = CreateCompilation(source2, assemblyName: "d03a3229-eb22-4682-88df-77efaa348e3b", references: new MetadataReference[] { new CSharpCompilationReference(compilation1) }); compilation2.VerifyDiagnostics( // (1,17): error CS0454: Circular constraint dependency involving 'T' and 'T' Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(1, 17), // (5,26): error CS0454: Circular constraint dependency involving 'T' and 'T' Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(5, 26)); var source3 = @"class C { static void M(A1<object> a) { } static void M(A2<object> a) { } static void M() { A3.M<object>(); } }"; var compilation3 = CreateCompilation(source3, references: new MetadataReference[] { new CSharpCompilationReference(compilation2) }); compilation3.VerifyDiagnostics( // (4,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A2<T>'. There is no implicit reference conversion from 'object' to 'B2'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A2<T>", "B2", "T", "object").WithLocation(4, 30), // (4,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A2<T>'. There is no implicit reference conversion from 'object' to 'I'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A2<T>", "I", "T", "object").WithLocation(4, 30), // (4,30): error CS0012: The type 'B2' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("B2", "d521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(4, 30), // (4,30): error CS0012: The type 'I' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A2<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("I", "d521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(4, 30), // (3,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A1<T>'. There is no implicit reference conversion from 'object' to 'B1'. // static void M(A1<object> a) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "a").WithArguments("A1<T>", "B1", "T", "object").WithLocation(3, 30), // (3,30): error CS0012: The type 'B1' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A1<object> a) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "a").WithArguments("B1", "d521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(3, 30), // (7,12): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A3.M<T>()'. There is no implicit reference conversion from 'object' to 'B3'. // A3.M<object>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<object>").WithArguments("A3.M<T>()", "B3", "T", "object").WithLocation(7, 12), // (7,12): error CS0012: The type 'B3' is defined in an assembly that is not referenced. You must add a reference to assembly 'd521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // A3.M<object>(); Diagnostic(ErrorCode.ERR_NoTypeDef, "M<object>").WithArguments("B3", "d521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 12)); } [WorkItem(542753, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542753")] [Fact] public void MissingTypeInVariantInterfaceConstraint() { var ilSource = @".assembly extern other {} .class interface public abstract I<T> { } .class interface public abstract IIn<-T> { } .class interface public abstract IOut<+T> { } .class public A0<(class [other]B)T> { } .class public A<(class I<class [other]B>)T> { } .class public AIn<(class IIn<class [other]B>)T> { } .class public AOut<(class IOut<class [other]B>)T> { }"; var csharpSource = @"class C { static void M(A0<object> o) { } static void M(A<I<object>> o) { } static void M(AIn<IIn<object>> o) { } static void M(AOut<IOut<object>> o) { } }"; CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics( // (3,30): error CS0012: The type 'B' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A0<object> o) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "o").WithArguments("B", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(3, 30), // (3,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A0<T>'. There is no implicit reference conversion from 'object' to 'B'. // static void M(A0<object> o) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("A0<T>", "B", "T", "object").WithLocation(3, 30), // (4,32): error CS0012: The type 'B' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(A<I<object>> o) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "o").WithArguments("B", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(4, 32), // (4,32): error CS0311: The type 'I<object>' cannot be used as type parameter 'T' in the generic type or method 'A<T>'. There is no implicit reference conversion from 'I<object>' to 'I<B>'. // static void M(A<I<object>> o) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("A<T>", "I<B>", "T", "I<object>").WithLocation(4, 32), // (5,36): error CS0012: The type 'B' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(AIn<IIn<object>> o) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "o").WithArguments("B", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(5, 36), // (5,36): error CS0311: The type 'I<object>' cannot be used as type parameter 'T' in the generic type or method 'AIn<T>'. There is no implicit reference conversion from 'IIn<object>' to 'IIn<B>'. // static void M(AIn<IIn<object>> o) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("AIn<T>", "IIn<B>", "T", "IIn<object>").WithLocation(5, 36), // (6,38): error CS0012: The type 'B' is defined in an assembly that is not referenced. You must add a reference to assembly 'other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // static void M(AOut<IOut<object>> o) { } Diagnostic(ErrorCode.ERR_NoTypeDef, "o").WithArguments("B", "other, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(6, 38), // (6,38): error CS0311: The type 'I<object>' cannot be used as type parameter 'T' in the generic type or method 'AOut<T>'. There is no implicit reference conversion from 'IOut<object>' to 'IOut<B>'. // static void M(AOut<IOut<object>> o) { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("AOut<T>", "IOut<B>", "T", "IOut<object>").WithLocation(6, 38)); } /// <summary> /// Similar to above but with unrecognized type /// rather than missing type, and all in source. /// </summary> [Fact] public void UnrecognizedTypeInVariantInterfaceConstraint() { var source = @"interface I<T> { } interface IIn<in T> { } interface IOut<out T> { } class A0<T> where T : B { } class A<T> where T : I<B> { } class AIn<T> where T : IIn<B> { } class AOut<T> where T : IOut<B> { } class C { static void M(A0<object> o) { } static void M(A<I<object>> o) { } static void M(AIn<IIn<object>> o) { } static void M(AOut<IOut<object>> o) { } }"; CreateCompilation(source).VerifyDiagnostics( // (4,23): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(4, 23), // (5,24): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(5, 24), // (6,28): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(6, 28), // (7,30): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(7, 30), // (10,30): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A0<T>'. There is no implicit reference conversion from 'object' to 'B'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("A0<T>", "B", "T", "object").WithLocation(10, 30), // (11,32): error CS0311: The type 'I<object>' cannot be used as type parameter 'T' in the generic type or method 'A<T>'. There is no implicit reference conversion from 'I<object>' to 'I<B>'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("A<T>", "I<B>", "T", "I<object>").WithLocation(11, 32), // (12,36): error CS0311: The type 'I<object>' cannot be used as type parameter 'T' in the generic type or method 'AIn<T>'. There is no implicit reference conversion from 'IIn<object>' to 'IIn<B>'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("AIn<T>", "IIn<B>", "T", "IIn<object>").WithLocation(12, 36), // (13,38): error CS0311: The type 'I<object>' cannot be used as type parameter 'T' in the generic type or method 'AOut<T>'. There is no implicit reference conversion from 'IOut<object>' to 'IOut<B>'. Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "o").WithArguments("AOut<T>", "IOut<B>", "T", "IOut<object>").WithLocation(13, 38)); } [WorkItem(542174, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542174")] [ClrOnlyFact] public void ConstraintsOnOverriddenMethod() { var source = @"interface I<T> where T : class { } abstract class A { public abstract I<T> F<T>() where T : class; } class B: A { public override I<U> F<U>() { return null; } }"; var comp = CreateCompilation(source); CompileAndVerify(comp); var method = comp.GetMember<MethodSymbol>("B.F"); Assert.Equal("I<U> B.F<U>() where U : class", method.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } [WorkItem(542264, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542264")] [Fact] public void PartialMethodsDifferentTypeParameterNames() { var source = @"interface I<T> { } partial class C { partial void M<T, U>(T t, U u) where T : U where U : I<T>; partial void M<X, Y>(X x, Y y) where X : Y where Y : I<X> { x.ToString(); y.ToString(); t.ToString(); u.ToString(); } partial void M<T1, T2>(T1 t1, T2 t2) where T1 : T2 where T2 : I<T1>; }"; CreateCompilation(source).VerifyDiagnostics( // (7,18): warning CS8826: Partial method declarations 'void C.M<T, U>(T t, U u)' and 'void C.M<X, Y>(X x, Y y)' have signature differences. // partial void M<X, Y>(X x, Y y) Diagnostic(ErrorCode.WRN_PartialMethodTypeDifference, "M").WithArguments("void C.M<T, U>(T t, U u)", "void C.M<X, Y>(X x, Y y)").WithLocation(7, 18), // (13,9): error CS0103: The name 't' does not exist in the current context // t.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "t").WithArguments("t").WithLocation(13, 9), // (14,9): error CS0103: The name 'u' does not exist in the current context // u.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "u").WithArguments("u").WithLocation(14, 9), // (16,18): error CS0756: A partial method may not have multiple defining declarations // partial void M<T1, T2>(T1 t1, T2 t2) Diagnostic(ErrorCode.ERR_PartialMethodOnlyOneLatent, "M").WithLocation(16, 18), // (16,18): error CS0111: Type 'C' already defines a member called 'M' with the same parameter types // partial void M<T1, T2>(T1 t1, T2 t2) Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M").WithArguments("M", "C").WithLocation(16, 18)); } [WorkItem(542331, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542331")] [Fact] public void InterfaceImplementationMismatchNewMethod() { var source = @"interface I { void M<T>() where T : class; } class A { public void M<T>() where T : class { } } class B : A { public new void M<T>() { } } class C1 : B, I { } class C2 : A, I { public new void M<T>() { } }"; CreateCompilation(source).VerifyDiagnostics( // (13,15): error CS0425: The constraints for type parameter 'T' of method 'B.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class C1 : B, I Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "B.M<T>()", "T", "I.M<T>()").WithLocation(13, 15), // (18,21): error CS0425: The constraints for type parameter 'T' of method 'C2.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // public new void M<T>() { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C2.M<T>()", "T", "I.M<T>()").WithLocation(18, 21)); } /// <summary> /// Same as above but with implementing class from metadata. /// </summary> [Fact] public void InterfaceImplementationMismatchNewMethodMetadata() { var ilSource = @".class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<class T>() { } } .class public A { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<class T>() { ret } } .class public B extends A { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public hidebysig instance void M<T>() { ret } } .class public C1 extends B implements I { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } }"; var csharpSource = @"class C2 : B, I { } class D { static void M1(I i) { } static void M2() { M1(new C1()); M1(new C2()); } }"; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); compilation.VerifyDiagnostics( // (1,15): error CS0425: The constraints for type parameter 'T' of method 'B.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // class C2 : B, I { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "B.M<T>()", "T", "I.M<T>()").WithLocation(1, 15)); // Arguably, B.M<T> should not be considered an implementation of // I.M<T> since the CLR does not consider it so. For now, however, // FindImplementationForInterfaceMember returns B.M<T>. var globalNamespace = compilation.GlobalNamespace; var im = globalNamespace.GetMember<NamedTypeSymbol>("I").GetMember<MethodSymbol>("M"); var bx = globalNamespace.GetMember<NamedTypeSymbol>("B").GetMember<MethodSymbol>("M"); var c1 = globalNamespace.GetMember<NamedTypeSymbol>("C1"); var impl = c1.FindImplementationForInterfaceMember(im); Assert.Equal(bx, impl); } [WorkItem(528855, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528855")] [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void ModReqsInConstraintsAreNotSupported() { var ilSource = @".class public A { } .class interface public abstract I { .method public abstract virtual instance void M<(class A modreq(int32))T>() { } } .class interface public abstract IT<(class A modreq(int32))T> { }"; var csharpSource = @"class C1 : I { void I.M<T>() { } } class C2 : IT<A> { } class C<T> : IT<T> { void M<U>() where U : T { } } class C3 : I { public virtual void M<T>() where T : A { } } "; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); compilation.VerifyDiagnostics( // (3,14): error CS0648: '' is a type not supported by the language // void I.M<T>() { } Diagnostic(ErrorCode.ERR_BogusType, "T").WithArguments("").WithLocation(3, 14), // (5,7): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'IT<T>'. There is no implicit reference conversion from 'A' to '?'. // class C2 : IT<A> Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "C2").WithArguments("IT<T>", "?", "T", "A").WithLocation(5, 7), // (5,7): error CS0648: '' is a type not supported by the language // class C2 : IT<A> Diagnostic(ErrorCode.ERR_BogusType, "C2").WithArguments("").WithLocation(5, 7), // (8,7): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'IT<T>'. There is no boxing conversion or type parameter conversion from 'T' to '?'. // class C<T> : IT<T> Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "C").WithArguments("IT<T>", "?", "T", "T").WithLocation(8, 7), // (8,7): error CS0648: '' is a type not supported by the language // class C<T> : IT<T> Diagnostic(ErrorCode.ERR_BogusType, "C").WithArguments("").WithLocation(8, 7), // (14,25): error CS0425: The constraints for type parameter 'T' of method 'C3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead. // public virtual void M<T>() where T : A { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C3.M<T>()", "T", "I.M<T>()").WithLocation(14, 25)); var m = ((NamedTypeSymbol)compilation.GetMember("C1")).GetMember("I.M"); var constraintType = ((SourceOrdinaryMethodSymbol)m).TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].Type; Assert.IsType<UnsupportedMetadataTypeSymbol>(constraintType); Assert.False(((NamedTypeSymbol)constraintType).IsSerializable); } /// <summary> /// Constraints with modopts are treated as unsupported types. /// (The native compiler imports constraints with modopts but /// generates invalid types when implementing or overriding /// generic methods with such constraints.) /// </summary> [WorkItem(528856, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528856")] [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void ModOptsInConstraintsAreIgnored() { var ilSource = @".class public A { .method public hidebysig specialname rtspecialname instance void .ctor() { ret } .method public virtual instance void M<(class A modopt(A) modopt(int32))T>() { ret } } .class interface public abstract I<(class A modopt(A))T> { .method public abstract virtual instance void M<(!T modopt(int32))U>() { } }"; var csharpSource = @"class B : A { public override void M<T>() { } } class C : I<A> { void I<A>.M<T>() { } } class P { static void Main() { new A().M<A>(); new B().M<A>(); ((I<A>)new C()).M<A>(); } }"; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); compilation.VerifyDiagnostics( // (5,7): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'I<T>'. There is no implicit reference conversion from 'A' to '?'. // class C : I<A> Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "C").WithArguments("I<T>", "?", "T", "A").WithLocation(5, 7), // (5,7): error CS0648: '' is a type not supported by the language // class C : I<A> Diagnostic(ErrorCode.ERR_BogusType, "C").WithArguments("").WithLocation(5, 7), // (7,10): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'I<T>'. There is no implicit reference conversion from 'A' to '?'. // void I<A>.M<T>() { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "I<A>").WithArguments("I<T>", "?", "T", "A").WithLocation(7, 10), // (7,10): error CS0648: '' is a type not supported by the language // void I<A>.M<T>() { } Diagnostic(ErrorCode.ERR_BogusType, "I<A>").WithArguments("").WithLocation(7, 10), // (7,17): error CS0648: '' is a type not supported by the language // void I<A>.M<T>() { } Diagnostic(ErrorCode.ERR_BogusType, "T").WithArguments("").WithLocation(7, 17), // (13,17): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'A.M<T>()'. There is no implicit reference conversion from 'A' to '?'. // new A().M<A>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<A>").WithArguments("A.M<T>()", "?", "T", "A").WithLocation(13, 17), // (13,17): error CS0648: '' is a type not supported by the language // new A().M<A>(); Diagnostic(ErrorCode.ERR_BogusType, "M<A>").WithArguments("").WithLocation(13, 17), // (15,13): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'I<T>'. There is no implicit reference conversion from 'A' to '?'. // ((I<A>)new C()).M<A>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "A").WithArguments("I<T>", "?", "T", "A").WithLocation(15, 13), // (15,13): error CS0648: '' is a type not supported by the language // ((I<A>)new C()).M<A>(); Diagnostic(ErrorCode.ERR_BogusType, "A").WithArguments("").WithLocation(15, 13), // (15,25): error CS0311: The type 'A' cannot be used as type parameter 'U' in the generic type or method 'I<A>.M<U>()'. There is no implicit reference conversion from 'A' to '?'. // ((I<A>)new C()).M<A>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<A>").WithArguments("I<A>.M<U>()", "?", "U", "A").WithLocation(15, 25), // (15,25): error CS0648: '' is a type not supported by the language // ((I<A>)new C()).M<A>(); Diagnostic(ErrorCode.ERR_BogusType, "M<A>").WithArguments("").WithLocation(15, 25)); } /// <summary> /// Constraints on the nested type must match /// constraints from the containing types. /// </summary> [WorkItem(528859, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528859")] [Fact] public void InconsistentConstraintsAreNotSupported() { var ilSource = @".class public A { .method public specialname rtspecialname instance void .ctor() { ret } } .class interface abstract public I { } .class interface abstract public IT<T> { .class interface abstract nested public IU<U> { } .class interface abstract nested public ITU<T, U> { } .class interface abstract nested public ITU2<(!U)T, U> { } .class interface abstract nested public IT<T> { .class interface abstract nested public IAI<(A, I)T> { } } .class interface abstract nested public IAI<(A, I)T> { .class interface abstract nested public IT<T> { } .class interface abstract nested public IAI<(A, I)T> { } } .class interface abstract nested public IF<class .ctor T> { } .class interface abstract nested public IIn<-T> { } } .class interface abstract public ITU<T, (!T)U> { .class interface abstract nested public ITU<T, (!T)U> { } .class interface abstract nested public ITU2<(!U)T, U> { } } .class abstract interface public IAI<(A, I)T> { .class interface abstract nested public IT<T> { .class interface abstract nested public IAI<(A, I)T> { } } .class nested public CIA<(I, A)T> { .method public specialname rtspecialname instance void .ctor() { ret } } } .class public CF<class .ctor T> { .method public specialname rtspecialname instance void .ctor() { ret } .class nested public CT<T> { .method public specialname rtspecialname instance void .ctor() { ret } } .class interface abstract nested public IF<.ctor class T> { } } .class interface abstract public IIn<-T> { .class interface abstract nested public IT<T> { } .class interface abstract nested public IInU<-U> { } .class interface abstract nested public IOut<+T> { } }"; var csharpSource = @"class C : A, I { } class P { static void M() { object o; o = typeof(IT<object>); o = typeof(IT<object>.IU); o = typeof(IT<object>.ITU<int>); o = typeof(IT<object>.ITU2<object>); // CS0648 o = typeof(IT<object>.IT.IAI); // CS0648 o = typeof(IT<object>.IAI); // CS0648 o = typeof(IT<object>.IAI.IT); // CS0648 o = typeof(IT<object>.IAI.IAI); // CS0648 o = typeof(IT<object>.IF); // CS0648 o = typeof(IT<object>.IIn); // CS0648 (not reported by Dev11) o = typeof(ITU<object, object>.ITU); o = typeof(ITU<object, object>.ITU2); // CS0648 o = typeof(IAI<C>); o = typeof(IAI<C>.IT); // CS0648 o = typeof(IAI<C>.IT.IAI); // CS0648 o = typeof(IAI<C>.CIA); o = typeof(CF<C>); o = typeof(CF<C>.CT); // CS0648 o = typeof(CF<C>.IF); o = typeof(IIn<object>); o = typeof(IIn<object>.IT); // CS0648 (not reported by Dev11) o = typeof(IIn<object>.IInU); o = typeof(IIn<object>.IOut); // CS0648 (not reported by Dev11) } }"; var compilation1 = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); compilation1.VerifyDiagnostics( // (10,31): error CS0648: 'IT<T>.ITU2<U>' is a type not supported by the language // o = typeof(IT<object>.ITU2<object>); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "ITU2<object>").WithArguments("IT<T>.ITU2<U>"), // (11,34): error CS0648: 'IT<T>.IT.IAI' is a type not supported by the language // o = typeof(IT<object>.IT.IAI); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IAI").WithArguments("IT<T>.IT.IAI"), // (12,31): error CS0648: 'IT<T>.IAI' is a type not supported by the language // o = typeof(IT<object>.IAI); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IAI").WithArguments("IT<T>.IAI"), // (13,31): error CS0648: 'IT<T>.IAI' is a type not supported by the language // o = typeof(IT<object>.IAI.IT); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IAI").WithArguments("IT<T>.IAI"), // (14,31): error CS0648: 'IT<T>.IAI' is a type not supported by the language // o = typeof(IT<object>.IAI.IAI); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IAI").WithArguments("IT<T>.IAI"), // (14,35): error CS0648: 'IT<T>.IAI.IAI' is a type not supported by the language // o = typeof(IT<object>.IAI.IAI); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IAI").WithArguments("IT<T>.IAI.IAI"), // (15,31): error CS0648: 'IT<T>.IF' is a type not supported by the language // o = typeof(IT<object>.IF); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IF").WithArguments("IT<T>.IF"), // (16,31): error CS0648: 'IT<T>.IIn' is a type not supported by the language // o = typeof(IT<object>.IIn); // CS0648 (not reported by Dev11) Diagnostic(ErrorCode.ERR_BogusType, "IIn").WithArguments("IT<T>.IIn"), // (18,40): error CS0648: 'ITU<T, U>.ITU2' is a type not supported by the language // o = typeof(ITU<object, object>.ITU2); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "ITU2").WithArguments("ITU<T, U>.ITU2"), // (20,27): error CS0648: 'IAI<T>.IT' is a type not supported by the language // o = typeof(IAI<C>.IT); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IT").WithArguments("IAI<T>.IT"), // (21,27): error CS0648: 'IAI<T>.IT' is a type not supported by the language // o = typeof(IAI<C>.IT.IAI); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "IT").WithArguments("IAI<T>.IT"), // (24,26): error CS0648: 'CF<T>.CT' is a type not supported by the language // o = typeof(CF<C>.CT); // CS0648 Diagnostic(ErrorCode.ERR_BogusType, "CT").WithArguments("CF<T>.CT"), // (27,32): error CS0648: 'IIn<T>.IT' is a type not supported by the language // o = typeof(IIn<object>.IT); // CS0648 (not reported by Dev11) Diagnostic(ErrorCode.ERR_BogusType, "IT").WithArguments("IIn<T>.IT"), // (29,32): error CS0648: 'IIn<T>.IOut' is a type not supported by the language // o = typeof(IIn<object>.IOut); // CS0648 (not reported by Dev11) Diagnostic(ErrorCode.ERR_BogusType, "IOut").WithArguments("IIn<T>.IOut")); } [WorkItem(528861, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528861")] [Fact] public void ConstraintsAreCheckedAlongHierarchy() { var ilSource = @".class interface public abstract I { } .class public abstract A { .method public specialname rtspecialname instance void .ctor() { ret } } .class interface public abstract IA1_1<valuetype T> { } .class interface public abstract IA1_2<(I)T> { } .class interface public abstract IA1_3<T, (!T)U> { } .class interface public abstract IB1<T, U, V> implements class IA1_1<!T>, class IA1_2<!U>, class IA1_3<!U, !V> { } .class interface public abstract IA2_1<valuetype T> { } .class interface public abstract IA2_2<(I)T> { } .class interface public abstract IA2_3<T, (!T)U> { } .class interface public abstract IB2<T, U, V> implements class IA2_1<!T>, class IA2_2<!U>, class IA2_3<!U, !V> { } .class interface public abstract IA3_1<valuetype T> { } .class interface public abstract IA3_2<(I)T> { } .class interface public abstract IA3_3<T, (!T)U> { } .class interface public abstract IB3_1<T> implements class IA3_1<!T> { } .class public abstract B3<T, U, V> implements class IA3_1<!T>, class IA3_2<!U>, class IA3_3<!U, !V> { .method public specialname rtspecialname instance void .ctor() { ret } } .class public abstract A4<valuetype T, (I)U, (!U)V> { .method public specialname rtspecialname instance void .ctor() { ret } } .class public abstract B4<T, U, V> extends class A4<!T, !U, !V> { .method public specialname rtspecialname instance void .ctor() { ret } }"; var csharpSource = @"interface IC1 : IB1<I, A, object> { } interface IC2<T, U, V> : IB2<T, U, V> { } interface IC3_1 : IB3_1<object> { } class C2 : IC2<I, A, object> { } class C3 : B3<I, A, object>, IC3_1 { } class C4 : B4<I, A, object> { } "; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); compilation.VerifyDiagnostics( // (1,11): error CS0453: The type 'I' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'IA1_1<T>' // interface IC1 : IB1<I, A, object> { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "IC1").WithArguments("IA1_1<T>", "T", "I").WithLocation(1, 11), // (1,11): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'IA1_2<T>'. There is no implicit reference conversion from 'A' to 'I'. // interface IC1 : IB1<I, A, object> { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "IC1").WithArguments("IA1_2<T>", "I", "T", "A").WithLocation(1, 11), // (1,11): error CS0311: The type 'object' cannot be used as type parameter 'U' in the generic type or method 'IA1_3<T, U>'. There is no implicit reference conversion from 'object' to 'A'. // interface IC1 : IB1<I, A, object> { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "IC1").WithArguments("IA1_3<T, U>", "A", "U", "object").WithLocation(1, 11), // (2,11): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'IA2_1<T>' // interface IC2<T, U, V> : IB2<T, U, V> { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "IC2").WithArguments("IA2_1<T>", "T", "T").WithLocation(2, 11), // (2,11): error CS0314: The type 'U' cannot be used as type parameter 'T' in the generic type or method 'IA2_2<T>'. There is no boxing conversion or type parameter conversion from 'U' to 'I'. // interface IC2<T, U, V> : IB2<T, U, V> { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "IC2").WithArguments("IA2_2<T>", "I", "T", "U").WithLocation(2, 11), // (2,11): error CS0314: The type 'V' cannot be used as type parameter 'U' in the generic type or method 'IA2_3<T, U>'. There is no boxing conversion or type parameter conversion from 'V' to 'U'. // interface IC2<T, U, V> : IB2<T, U, V> { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "IC2").WithArguments("IA2_3<T, U>", "U", "U", "V").WithLocation(2, 11), // (3,11): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'IA3_1<T>' // interface IC3_1 : IB3_1<object> { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "IC3_1").WithArguments("IA3_1<T>", "T", "object").WithLocation(3, 11), // (4,7): error CS0453: The type 'I' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'IA2_1<T>' // class C2 : IC2<I, A, object> { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C2").WithArguments("IA2_1<T>", "T", "I").WithLocation(4, 7), // (4,7): error CS0311: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'IA2_2<T>'. There is no implicit reference conversion from 'A' to 'I'. // class C2 : IC2<I, A, object> { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "C2").WithArguments("IA2_2<T>", "I", "T", "A").WithLocation(4, 7), // (4,7): error CS0311: The type 'object' cannot be used as type parameter 'U' in the generic type or method 'IA2_3<T, U>'. There is no implicit reference conversion from 'object' to 'A'. // class C2 : IC2<I, A, object> { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "C2").WithArguments("IA2_3<T, U>", "A", "U", "object").WithLocation(4, 7), // (5,7): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'IA3_1<T>' // class C3 : B3<I, A, object>, IC3_1 { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C3").WithArguments("IA3_1<T>", "T", "object").WithLocation(5, 7)); } [WorkItem(542755, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542755")] [ClrOnlyFact] public void SpellingOfGenericClassNameIsPreserved() { var ilSource = @" .class interface public abstract I2<T> { } .class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<(class I2<string>) T>() { } } "; var csharpSource = @" class C : I { void I.M<T>() { } } "; Action<CSharpCompilation> compilationVerifier = delegate (CSharpCompilation compilation) { NamedTypeSymbol i2 = compilation.GetTypeByMetadataName("I2"); Assert.False(i2.IsErrorType()); Assert.Equal(1, i2.Arity); Assert.Equal("I2", i2.Name); Assert.False(i2.MangleName); Assert.Equal("I2<T>", i2.ToTestDisplayString()); Assert.Equal("I2", i2.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)); }; CompileWithCustomILSource(csharpSource, ilSource, compilationVerifier: compilationVerifier); } [ClrOnlyFact] public void SpellingOfGenericClassNameIsPreserved2() { var ilSource = @" .class interface public abstract I2`2<T> { } .class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<(class I2`2<string>) T>() { } } "; var csharpSource = @" class C : I { void I.M<T>() { } } "; Action<CSharpCompilation> compilationVerifier = delegate (CSharpCompilation compilation) { NamedTypeSymbol i2 = compilation.GetTypeByMetadataName("I2`2"); Assert.False(i2.IsErrorType()); Assert.Equal(1, i2.Arity); Assert.Equal("I2`2", i2.Name); Assert.False(i2.MangleName); Assert.Equal("I2`2<T>", i2.ToTestDisplayString()); Assert.Equal("I2`2", i2.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)); }; CompileWithCustomILSource(csharpSource, ilSource, compilationVerifier: compilationVerifier); } [ClrOnlyFact] public void SpellingOfGenericClassNameIsPreserved3() { var ilSource = @" .class interface public abstract I2`1<T> { } .class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<(class I2`1<string>) T>() { } } "; var csharpSource = @" class C : I { void I.M<T>() { } } "; Action<CSharpCompilation> compilationVerifier = delegate (CSharpCompilation compilation) { NamedTypeSymbol i2 = compilation.GetTypeByMetadataName("I2`1"); Assert.False(i2.IsErrorType()); Assert.Equal(1, i2.Arity); Assert.Equal("I2", i2.Name); Assert.True(i2.MangleName); Assert.Equal("I2<T>", i2.ToTestDisplayString()); Assert.Equal("I2`1", i2.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)); }; CompileWithCustomILSource(csharpSource, ilSource, compilationVerifier: compilationVerifier); } [ClrOnlyFact] public void SpellingOfGenericClassNameIsPreserved4() { var ilSource = @" .class interface public abstract I2`01<T> { } .class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<(class I2`01<string>) T>() { } } "; var csharpSource = @" class C : I { void I.M<T>() { } } "; Action<CSharpCompilation> compilationVerifier = delegate (CSharpCompilation compilation) { NamedTypeSymbol i2 = compilation.GetTypeByMetadataName("I2`01"); Assert.False(i2.IsErrorType()); Assert.Equal(1, i2.Arity); Assert.Equal("I2`01", i2.Name); Assert.False(i2.MangleName); Assert.Equal("I2`01<T>", i2.ToTestDisplayString()); Assert.Equal("I2`01", i2.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)); }; CompileWithCustomILSource(csharpSource, ilSource, compilationVerifier: compilationVerifier); } [ConditionalFact(typeof(ClrOnly), typeof(DesktopOnly))] public void SpellingOfGenericClassNameIsPreserved5() { var ilSource = @" .class interface public abstract I2`1 { } .class interface public abstract I { .method public hidebysig newslot abstract virtual instance void M<(class I2`1) T>() { } .class interface nested public abstract I2`1 { } .class interface nested public abstract I { } .class interface nested public abstract I3`1<T> { } .class interface nested public abstract I4`2<T> { } } .class interface public System.IEquatable`1 { } .class interface public System.Linq.IQueryable`1 { } .class interface public System.Linq.IQueryable<T> { } .class interface public abstract I3`1<T> { } .class interface public abstract I4`2<T> { } "; var csharpSource = @" class C : I { void I.M<T>() { } } "; Action<CSharpCompilation> compilationVerifier = delegate (CSharpCompilation compilation) { NamedTypeSymbol i2 = compilation.GetTypeByMetadataName("I2`1"); Assert.False(i2.IsErrorType()); Assert.Equal(0, i2.Arity); Assert.Equal("I2`1", i2.Name); Assert.False(i2.MangleName); Assert.Equal("I2`1", i2.ToTestDisplayString()); Assert.Equal("I2`1", i2.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)); NamedTypeSymbol iEquatable = compilation.GetWellKnownType(WellKnownType.System_IEquatable_T); Assert.False(iEquatable.IsErrorType()); Assert.Equal(1, iEquatable.Arity); Assert.Same(iEquatable, compilation.GetTypeByMetadataName("System.IEquatable`1")); NamedTypeSymbol iQueryable_T = compilation.GetWellKnownType(WellKnownType.System_Linq_IQueryable_T); Assert.True(iQueryable_T.IsErrorType()); Assert.Equal(1, iQueryable_T.Arity); NamedTypeSymbol iQueryable = compilation.GetWellKnownType(WellKnownType.System_Linq_IQueryable); Assert.True(iQueryable.IsErrorType()); Assert.Equal(0, iQueryable.Arity); MetadataTypeName mdName; NamedTypeSymbol t; AssemblySymbol asm = i2.ContainingAssembly; mdName = MetadataTypeName.FromFullName("I3`1", false, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", false, 0); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I3`1", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", false, 1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", false, 2); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I3`1", t.Name); Assert.False(t.MangleName); Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", true, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); //mdName = MetadataTypeName.FromFullName("I3`1", true, 0); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I3`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", true, 1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); //mdName = MetadataTypeName.FromFullName("I3`1", true, 2); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I3`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I", false, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I", false, 0); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I", false, 1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I", true, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I", true, 0); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); //mdName = MetadataTypeName.FromFullName("I", true, 1); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I", t.Name); //Assert.False(t.MangleName); //Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I2`1", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, 0); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I2`1", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, 1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I2", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, 2); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I2`1", t.Name); Assert.False(t.MangleName); Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", true, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I2", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); //mdName = MetadataTypeName.FromFullName("I2`1", true, 0); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I2`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", true, 1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I2", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); //mdName = MetadataTypeName.FromFullName("I2`1", true, 2); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I2`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I4`2", t.Name); Assert.False(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, 0); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I4`2", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, 1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.False(t.IsErrorType()); Assert.Equal("I4`2", t.Name); Assert.False(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, 2); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I4", t.Name); Assert.True(t.MangleName); Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", true, -1); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I4", t.Name); Assert.True(t.MangleName); Assert.Equal(2, t.Arity); //mdName = MetadataTypeName.FromFullName("I4`2", true, 0); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I4`2", t.Name); //Assert.False(t.MangleName); //Assert.Equal(0, t.Arity); //mdName = MetadataTypeName.FromFullName("I4`2", true, 1); //t = asm.LookupTopLevelMetadataType(ref mdName, true); //Assert.True(t.IsErrorType()); //Assert.Equal("I4`2", t.Name); //Assert.False(t.MangleName); //Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", true, 2); t = asm.LookupDeclaredOrForwardedTopLevelMetadataType(ref mdName, visitedAssemblies: null); Assert.True(t.IsErrorType()); Assert.Equal("I4", t.Name); Assert.True(t.MangleName); Assert.Equal(2, t.Arity); NamedTypeSymbol containingType = compilation.GetTypeByMetadataName("I"); mdName = MetadataTypeName.FromFullName("I3`1", false, -1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", false, 0); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I3`1", false, 1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", false, 2); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I3`1", true, -1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); //mdName = MetadataTypeName.FromFullName("I3`1", true, 0); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I3`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I3`1", true, 1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I3", t.Name); Assert.True(t.MangleName); Assert.Equal(1, t.Arity); //mdName = MetadataTypeName.FromFullName("I3`1", true, 2); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I3`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I", false, -1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I", false, 0); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I", false, 1); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I", true, -1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I", true, 0); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); //mdName = MetadataTypeName.FromFullName("I", true, 1); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I", t.Name); //Assert.False(t.MangleName); //Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, -1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I2`1", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, 0); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I2`1", t.Name); Assert.False(t.MangleName); Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", false, 1); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I2`1", false, 2); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I2`1", true, -1); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); //mdName = MetadataTypeName.FromFullName("I2`1", true, 0); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I2`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(0, t.Arity); mdName = MetadataTypeName.FromFullName("I2`1", true, 1); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); //mdName = MetadataTypeName.FromFullName("I2`1", true, 2); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I2`1", t.Name); //Assert.False(t.MangleName); //Assert.Equal(2, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, -1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I4`2", t.Name); Assert.False(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, 0); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I4`2", false, 1); t = containingType.LookupMetadataType(ref mdName); Assert.False(t.IsErrorType()); Assert.Equal("I4`2", t.Name); Assert.False(t.MangleName); Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", false, 2); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); mdName = MetadataTypeName.FromFullName("I4`2", true, -1); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); //mdName = MetadataTypeName.FromFullName("I4`2", true, 0); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I4`2", t.Name); //Assert.False(t.MangleName); //Assert.Equal(0, t.Arity); //mdName = MetadataTypeName.FromFullName("I4`2", true, 1); //t = containingType.LookupMetadataType(ref mdName); //Assert.True(t.IsErrorType()); //Assert.Equal("I4`2", t.Name); //Assert.False(t.MangleName); //Assert.Equal(1, t.Arity); mdName = MetadataTypeName.FromFullName("I4`2", true, 2); t = containingType.LookupMetadataType(ref mdName); Assert.Null(t); }; CompileWithCustomILSource(csharpSource, ilSource, compilationVerifier: compilationVerifier, targetFramework: TargetFramework.Mscorlib40); } [WorkItem(542358, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542358")] [Fact] public void InterfaceConstraintsAbsorbed() { var source = @"interface I<T> { void M<U>() where U : struct, T; } class C : I<System.ValueType> { public void M<U>() where U : struct { } }"; CreateCompilation(source).VerifyDiagnostics(); } [WorkItem(542359, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542359")] [Fact] public void ExplicitImplementationMethodConstraintViolations() { var source = @"interface IA<T, U> { void M<V>() where V : T, U; } interface IB<T> { void M<U>() where U : struct, T; } interface IC<T> { void M<U>() where U : class, T; } interface ID<T> { void M<U>() where U : T, new(); } class C : IA<int, double>, IB<string>, IC<int>, ID<string> { void IA<int, double>.M<V>() { } void IB<string>.M<U>() { } void IC<int>.M<U>() { } void ID<string>.M<U>() { } }"; CreateCompilation(source).VerifyDiagnostics( // (19,28): error CS0455: Type parameter 'V' inherits conflicting constraints 'double' and 'int' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "V").WithArguments("V", "double", "int").WithLocation(19, 28), // (20,23): error CS0455: Type parameter 'U' inherits conflicting constraints 'string' and 'System.ValueType' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "U").WithArguments("U", "string", "System.ValueType").WithLocation(20, 23), // (20,23): error CS0455: Type parameter 'U' inherits conflicting constraints 'System.ValueType' and 'struct' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "U").WithArguments("U", "System.ValueType", "struct").WithLocation(20, 23), // (21,20): error CS0455: Type parameter 'U' inherits conflicting constraints 'int' and 'class' Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "U").WithArguments("U", "int", "class").WithLocation(21, 20)); } [WorkItem(542362, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542362")] [Fact] public void CycleInvolvingAlias() { var source = @"using C = B<A>; class A : C { } class B<T> where T : C { }"; CreateCompilation(source).VerifyDiagnostics(); } [WorkItem(542363, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542363")] [Fact] public void InvokeExplicitImplementationMethod() { var source = @"interface IA { object M(object o); object P { get; set; } } interface IB { void M<T>(T t) where T : IA; } class C : IB { void IB.M<T>(T t) { t.P = t.M(t.P); } }"; CreateCompilation(source).VerifyDiagnostics(); } [WorkItem(542364, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542364")] [Fact] public void CheckConstraintsOverriddenMethodDefaultParameter() { var source = @"abstract class B<T> { public abstract void F<S>(S x) where S : T; } class C : B<int> { public override void F<S>(S x = 0) { } }"; CreateCompilation(source).VerifyDiagnostics( // (7,33): error CS1750: A value of type 'int' cannot be used as a default parameter because there are no standard conversions to type 'S' Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "x").WithArguments("int", "S").WithLocation(7, 33)); } [WorkItem(542366, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542366")] [Fact] public void NestedConstraintsWithinConstraints() { var source = @"class A<T> where T : class { internal interface I { } } class B1 { internal class B2<T, U> where U : struct { } } class C1<T> where T : class, A<int>.I { } class C2<T> where T : A<B1.B2<object, A<T>>> { } class C3<T, U> where U : T, A<A<A<int>[]>[]>.I { } interface I { void M1<T>() where T : class, A<int>.I; void M2<T>() where T : A<B1.B2<object, A<T>>>; void M3<T, U>() where U : T, A<A<A<int>[]>[]>.I; }"; CreateCompilation(source).VerifyDiagnostics( // (9,10): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "T").WithArguments("A<T>", "T", "int").WithLocation(9, 10), // (10,10): error CS0453: The type 'A<T>' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B1.B2<T, U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "T").WithArguments("B1.B2<T, U>", "U", "A<T>").WithLocation(10, 10), // (11,13): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "U").WithArguments("A<T>", "T", "int").WithLocation(11, 13), // (14,13): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "T").WithArguments("A<T>", "T", "int").WithLocation(14, 13), // (15,13): error CS0453: The type 'A<T>' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'B1.B2<T, U>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "T").WithArguments("B1.B2<T, U>", "U", "A<T>").WithLocation(15, 13), // (16,16): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'A<T>' Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "U").WithArguments("A<T>", "T", "int").WithLocation(16, 16)); } [WorkItem(542367, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542367")] [Fact] public void ConstraintChecksBeforeOverloadResolution() { var source = @"class C<T> where T : class { } class Program { static void Main() { Goo<int>(null); } static void Goo<T>(object x) { } static void Goo<T>(C<T> x) where T : class { } }"; CreateCompilation(source).VerifyDiagnostics(); } [WorkItem(542380, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542380")] [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void StructProperties() { var source = @"interface I { int P { get; set; } int this[int index] { get; set; } } struct S : I { private int i; public int P { get; set; } public int this[int index] { get { return i; } set { i = value; } } } class A : I { private int i; public int P { get; set; } public int this[int index] { get { return i; } set { i = value; } } } class B { static void M1<T>(T t) where T : I { t.P++; t[0]++; t.P += 2; t[0] += 2; System.Console.WriteLine(""{0}, {1}"", t.P, t[0]); } static void M2<T>(T t) where T : class, I { t.P++; t[0]++; t.P += 2; t[0] += 2; System.Console.WriteLine(""{0}, {1}"", t.P, t[0]); } static void M3<T>(T t) where T : struct, I { t.P++; t[0]++; t.P += 2; t[0] += 2; System.Console.WriteLine(""{0}, {1}"", t.P, t[0]); } static void Main() { var a = new A(); var s = new S(); M1(a); M1(s); M2(a); M3(s); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"3, 3 3, 3 6, 6 3, 3"); compilation.VerifyIL("B.M1<T>(T)", @" { // Code size 290 (0x122) .maxstack 4 .locals init (T V_0, T& V_1, int V_2, T V_3, T& V_4) IL_0000: ldarga.s V_0 IL_0002: stloc.1 IL_0003: ldloca.s V_3 IL_0005: initobj ""T"" IL_000b: ldloc.3 IL_000c: box ""T"" IL_0011: brtrue.s IL_001e IL_0013: ldloc.1 IL_0014: ldobj ""T"" IL_0019: stloc.0 IL_001a: ldloca.s V_0 IL_001c: br.s IL_001f IL_001e: ldloc.1 IL_001f: dup IL_0020: constrained. ""T"" IL_0026: callvirt ""int I.P.get"" IL_002b: stloc.2 IL_002c: ldloc.2 IL_002d: ldc.i4.1 IL_002e: add IL_002f: constrained. ""T"" IL_0035: callvirt ""void I.P.set"" IL_003a: ldarga.s V_0 IL_003c: stloc.1 IL_003d: ldloca.s V_3 IL_003f: initobj ""T"" IL_0045: ldloc.3 IL_0046: box ""T"" IL_004b: brtrue.s IL_0058 IL_004d: ldloc.1 IL_004e: ldobj ""T"" IL_0053: stloc.0 IL_0054: ldloca.s V_0 IL_0056: br.s IL_0059 IL_0058: ldloc.1 IL_0059: dup IL_005a: ldc.i4.0 IL_005b: constrained. ""T"" IL_0061: callvirt ""int I.this[int].get"" IL_0066: stloc.2 IL_0067: ldc.i4.0 IL_0068: ldloc.2 IL_0069: ldc.i4.1 IL_006a: add IL_006b: constrained. ""T"" IL_0071: callvirt ""void I.this[int].set"" IL_0076: ldarga.s V_0 IL_0078: stloc.s V_4 IL_007a: ldloca.s V_3 IL_007c: initobj ""T"" IL_0082: ldloc.3 IL_0083: box ""T"" IL_0088: brtrue.s IL_0096 IL_008a: ldloc.s V_4 IL_008c: ldobj ""T"" IL_0091: stloc.0 IL_0092: ldloca.s V_0 IL_0094: br.s IL_0098 IL_0096: ldloc.s V_4 IL_0098: stloc.1 IL_0099: ldloc.1 IL_009a: ldloc.1 IL_009b: constrained. ""T"" IL_00a1: callvirt ""int I.P.get"" IL_00a6: ldc.i4.2 IL_00a7: add IL_00a8: constrained. ""T"" IL_00ae: callvirt ""void I.P.set"" IL_00b3: ldarga.s V_0 IL_00b5: stloc.1 IL_00b6: ldloca.s V_3 IL_00b8: initobj ""T"" IL_00be: ldloc.3 IL_00bf: box ""T"" IL_00c4: brtrue.s IL_00d1 IL_00c6: ldloc.1 IL_00c7: ldobj ""T"" IL_00cc: stloc.0 IL_00cd: ldloca.s V_0 IL_00cf: br.s IL_00d2 IL_00d1: ldloc.1 IL_00d2: stloc.s V_4 IL_00d4: ldloc.s V_4 IL_00d6: ldc.i4.0 IL_00d7: ldloc.s V_4 IL_00d9: ldc.i4.0 IL_00da: constrained. ""T"" IL_00e0: callvirt ""int I.this[int].get"" IL_00e5: ldc.i4.2 IL_00e6: add IL_00e7: constrained. ""T"" IL_00ed: callvirt ""void I.this[int].set"" IL_00f2: ldstr ""{0}, {1}"" IL_00f7: ldarga.s V_0 IL_00f9: constrained. ""T"" IL_00ff: callvirt ""int I.P.get"" IL_0104: box ""int"" IL_0109: ldarga.s V_0 IL_010b: ldc.i4.0 IL_010c: constrained. ""T"" IL_0112: callvirt ""int I.this[int].get"" IL_0117: box ""int"" IL_011c: call ""void System.Console.WriteLine(string, object, object)"" IL_0121: ret } "); compilation.VerifyIL("B.M2<T>(T)", @" { // Code size 172 (0xac) .maxstack 4 .locals init (T V_0, int V_1, T& V_2) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: dup IL_0005: constrained. ""T"" IL_000b: callvirt ""int I.P.get"" IL_0010: stloc.1 IL_0011: ldloc.1 IL_0012: ldc.i4.1 IL_0013: add IL_0014: constrained. ""T"" IL_001a: callvirt ""void I.P.set"" IL_001f: ldarg.0 IL_0020: stloc.0 IL_0021: ldloca.s V_0 IL_0023: dup IL_0024: ldc.i4.0 IL_0025: constrained. ""T"" IL_002b: callvirt ""int I.this[int].get"" IL_0030: stloc.1 IL_0031: ldc.i4.0 IL_0032: ldloc.1 IL_0033: ldc.i4.1 IL_0034: add IL_0035: constrained. ""T"" IL_003b: callvirt ""void I.this[int].set"" IL_0040: ldarg.0 IL_0041: stloc.0 IL_0042: ldloca.s V_0 IL_0044: stloc.2 IL_0045: ldloc.2 IL_0046: ldloc.2 IL_0047: constrained. ""T"" IL_004d: callvirt ""int I.P.get"" IL_0052: ldc.i4.2 IL_0053: add IL_0054: constrained. ""T"" IL_005a: callvirt ""void I.P.set"" IL_005f: ldarg.0 IL_0060: stloc.0 IL_0061: ldloca.s V_0 IL_0063: stloc.2 IL_0064: ldloc.2 IL_0065: ldc.i4.0 IL_0066: ldloc.2 IL_0067: ldc.i4.0 IL_0068: constrained. ""T"" IL_006e: callvirt ""int I.this[int].get"" IL_0073: ldc.i4.2 IL_0074: add IL_0075: constrained. ""T"" IL_007b: callvirt ""void I.this[int].set"" IL_0080: ldstr ""{0}, {1}"" IL_0085: ldarg.0 IL_0086: box ""T"" IL_008b: callvirt ""int I.P.get"" IL_0090: box ""int"" IL_0095: ldarg.0 IL_0096: box ""T"" IL_009b: ldc.i4.0 IL_009c: callvirt ""int I.this[int].get"" IL_00a1: box ""int"" IL_00a6: call ""void System.Console.WriteLine(string, object, object)"" IL_00ab: ret } "); compilation.VerifyIL("B.M3<T>(T)", @" { // Code size 166 (0xa6) .maxstack 4 .locals init (int V_0, T& V_1) IL_0000: ldarga.s V_0 IL_0002: dup IL_0003: constrained. ""T"" IL_0009: callvirt ""int I.P.get"" IL_000e: stloc.0 IL_000f: ldloc.0 IL_0010: ldc.i4.1 IL_0011: add IL_0012: constrained. ""T"" IL_0018: callvirt ""void I.P.set"" IL_001d: ldarga.s V_0 IL_001f: dup IL_0020: ldc.i4.0 IL_0021: constrained. ""T"" IL_0027: callvirt ""int I.this[int].get"" IL_002c: stloc.0 IL_002d: ldc.i4.0 IL_002e: ldloc.0 IL_002f: ldc.i4.1 IL_0030: add IL_0031: constrained. ""T"" IL_0037: callvirt ""void I.this[int].set"" IL_003c: ldarga.s V_0 IL_003e: dup IL_003f: constrained. ""T"" IL_0045: callvirt ""int I.P.get"" IL_004a: ldc.i4.2 IL_004b: add IL_004c: constrained. ""T"" IL_0052: callvirt ""void I.P.set"" IL_0057: ldarga.s V_0 IL_0059: stloc.1 IL_005a: ldloc.1 IL_005b: ldc.i4.0 IL_005c: ldloc.1 IL_005d: ldc.i4.0 IL_005e: constrained. ""T"" IL_0064: callvirt ""int I.this[int].get"" IL_0069: ldc.i4.2 IL_006a: add IL_006b: constrained. ""T"" IL_0071: callvirt ""void I.this[int].set"" IL_0076: ldstr ""{0}, {1}"" IL_007b: ldarga.s V_0 IL_007d: constrained. ""T"" IL_0083: callvirt ""int I.P.get"" IL_0088: box ""int"" IL_008d: ldarga.s V_0 IL_008f: ldc.i4.0 IL_0090: constrained. ""T"" IL_0096: callvirt ""int I.this[int].get"" IL_009b: box ""int"" IL_00a0: call ""void System.Console.WriteLine(string, object, object)"" IL_00a5: ret } "); } [WorkItem(542527, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542527")] [ClrOnlyFact] public void SelfReferentialInheritedConstraints01() { var source = @"using System; abstract class A<T> { public virtual void M1<U>() where U : IComparable<T>, T { } public virtual void M2<U>() where U : IComparable<U> { } public virtual void M3<U>() where U : IComparable<U>, T { } } class C : A<string> { public override void M1<U>() { Console.WriteLine(typeof(U)); } public override void M2<U>() { Console.WriteLine(typeof(U)); } public override void M3<U>() { Console.WriteLine(typeof(U)); } static void Main() { var c = new C(); c.M1<string>(); c.M2<string>(); c.M3<string>(); } }"; CompileAndVerify(source, expectedOutput: @"System.String System.String System.String"); } [ClrOnlyFact] public void SelfReferentialInheritedConstraints02() { var source = @"interface IA<T> { } class A<T> { internal class B<U> { } } abstract class C { internal abstract void M1<T, U>() where T : IA<A<T>.B<object>> where U : A<U[]>.B<T>; } interface IB { void M2<T, U>() where T : IA<A<T>.B<object>> where U : A<U[]>.B<T>; } class D : C { internal override void M1<X, Y>() { } } abstract class E : D, IB { internal abstract override void M1<T1, T2>(); void IB.M2<X, Y>() { } }"; Action<ModuleSymbol> validator = module => { var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("E"); var method = type.GetMember<MethodSymbol>("M1"); var typeParameter = method.TypeParameters[0]; Assert.Equal("IA<A<T1>.B<object>>", typeParameter.ConstraintTypes()[0].ToDisplayString()); CheckTypeParameterContainingSymbols(method, typeParameter.EffectiveBaseClassNoUseSiteDiagnostics, 0); CheckTypeParameterContainingSymbols(method, typeParameter.EffectiveInterfacesNoUseSiteDiagnostics[0], 1); CheckTypeParameterContainingSymbols(method, typeParameter.ConstraintTypes()[0], 1); typeParameter = method.TypeParameters[1]; Assert.Equal("A<T2[]>.B<T1>", typeParameter.ConstraintTypes()[0].ToDisplayString()); CheckTypeParameterContainingSymbols(method, typeParameter.EffectiveBaseClassNoUseSiteDiagnostics, 2); CheckTypeParameterContainingSymbols(method, typeParameter.ConstraintTypes()[0], 2); method = type.GetMethod("IB.M2"); typeParameter = method.TypeParameters[0]; Assert.Equal("IA<A<X>.B<object>>", typeParameter.ConstraintTypes()[0].ToDisplayString()); CheckTypeParameterContainingSymbols(method, typeParameter.EffectiveBaseClassNoUseSiteDiagnostics, 0); CheckTypeParameterContainingSymbols(method, typeParameter.EffectiveInterfacesNoUseSiteDiagnostics[0], 1); CheckTypeParameterContainingSymbols(method, typeParameter.ConstraintTypes()[0], 1); typeParameter = method.TypeParameters[1]; Assert.Equal("A<Y[]>.B<X>", typeParameter.ConstraintTypes()[0].ToDisplayString()); CheckTypeParameterContainingSymbols(method, typeParameter.EffectiveBaseClassNoUseSiteDiagnostics, 2); CheckTypeParameterContainingSymbols(method, typeParameter.ConstraintTypes()[0], 2); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } [WorkItem(542601, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542601")] [ClrOnlyFact] public void SelfReferentialInheritedConstraints03() { var source = @"using System; abstract class A { public abstract void Goo<T>() where T : IComparable<T>; } class B<S> : A { public override void Goo<T>() { Console.WriteLine(typeof(S)); Console.WriteLine(typeof(T)); } } class P { static void Main() { new B<string>().Goo<int>(); } } "; CompileAndVerify(source, expectedOutput: @"System.String System.Int32"); } [WorkItem(542601, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542601")] [ClrOnlyFact] public void SelfReferentialInheritedConstraints04() { var source = @"interface I<T> { } class A<T> { internal static void M<U>() where U : I<T>, I<U> { } internal class B<U> where U : I<T>, I<U> { } } class C : I<object>, I<C> { static void M() { A<object>.M<C>(); new A<object>.B<C>(); } }"; CompileAndVerify(source); } /// <summary> /// Verify any type parameter symbols within the type /// have the given containing method symbol. /// </summary> private void CheckTypeParameterContainingSymbols(MethodSymbol containingMethod, TypeSymbol type, int nReferencesExpected) { int nReferences = 0; type.VisitType((t, unused1, unused2) => { if (t.TypeKind == TypeKind.TypeParameter) { nReferences++; Assert.Same(t.ContainingSymbol, containingMethod); } return false; }, (object)null); Assert.Equal(nReferencesExpected, nReferences); } [WorkItem(542532, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542532")] [ClrOnlyFact] public void SelfReferentialConstraintsWithLambda() { var source = @"using System; class A<T> { } abstract class B { internal abstract void M<T, U>() where U : A<T>; } class C : B { internal override void M<T, U>() { Action a = () => Console.WriteLine(""M1<T, U>""); a(); } } class Program { static void M<T>(T x) where T : IComparable<T> { Action a = () => Console.WriteLine(x.CompareTo(x)); a(); } static void Main() { M(string.Empty); (new C()).M<int, A<int>>(); } }"; CompileAndVerify(source, expectedOutput: @"0 M1<T, U>"); } [WorkItem(542277, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542277")] [ClrOnlyFact] public void AccessToMembersOfInheritedConstraints() { var source = @" using System; abstract class A<T> { public abstract void Goo<S>() where S : T, new(); } class B : A<S> { public override void Goo<S>() { var s = new S(); s.X = 5; Console.WriteLine(s.X); } static void Main() { new B().Goo<S>(); } } class S { public int X; } "; CompileAndVerify(source, expectedOutput: "5"); } [WorkItem(542564, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542564")] [Fact] public void Arrays() { var source = @"class A<T> { static int[] F0(object[] x) { return (int[])x; } static U[] F1<U>(T[] x) where U : class, T { return (U[])x; } static U[] F2<U>(T[] x) where U : struct, T { return (U[])x; } static U[] F3<U>(T[] x) where U : T { return (U[])x; } } class B<T> { static object[] F0(int[] x) { return (object[])x; } static T[] F1<U>(U[] x) where U : class, T { return (T[])x; } static T[] F2<U>(U[] x) where U : struct, T { return (T[])x; } static T[] F3<U>(U[] x) where U : T { return (T[])x; } }"; CreateCompilation(source).VerifyDiagnostics( // (5,16): error CS0030: Cannot convert type 'object[]' to 'int[]' Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int[])x").WithArguments("object[]", "int[]").WithLocation(5, 16), // (13,16): error CS0030: Cannot convert type 'T[]' to 'U[]' Diagnostic(ErrorCode.ERR_NoExplicitConv, "(U[])x").WithArguments("T[]", "U[]").WithLocation(13, 16), // (17,16): error CS0030: Cannot convert type 'T[]' to 'U[]' Diagnostic(ErrorCode.ERR_NoExplicitConv, "(U[])x").WithArguments("T[]", "U[]").WithLocation(17, 16), // (24,16): error CS0030: Cannot convert type 'int[]' to 'object[]' Diagnostic(ErrorCode.ERR_NoExplicitConv, "(object[])x").WithArguments("int[]", "object[]").WithLocation(24, 16), // (32,16): error CS0030: Cannot convert type 'U[]' to 'T[]' Diagnostic(ErrorCode.ERR_NoExplicitConv, "(T[])x").WithArguments("U[]", "T[]").WithLocation(32, 16), // (36,16): error CS0030: Cannot convert type 'U[]' to 'T[]' Diagnostic(ErrorCode.ERR_NoExplicitConv, "(T[])x").WithArguments("U[]", "T[]").WithLocation(36, 16)); } [ClrOnlyFact] public void ImplicitReferenceTypeParameterConversion() { var source = @"class C<T, U> where U : class, T { static U F1(T x) { return (U)x; } static T F2(U x) { return x; } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C<T, U>.F1(T)", @"{ // Code size 12 (0xc) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""T"" IL_0006: unbox.any ""U"" IL_000b: ret }"); compilation.VerifyIL("C<T, U>.F2(U)", @"{ // Code size 12 (0xc) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""U"" IL_0006: unbox.any ""T"" IL_000b: ret }"); } [WorkItem(542620, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542620")] [ClrOnlyFact] public void DuplicateConstraintTypes() { var source = @"interface I<T> { } interface I1<T, U> { void M<V>() where V : T, U; } interface I2<T, U> { void M<V>() where V : T, I<U>, I<object>; } interface I3<T, U> { void M<V>() where V : I<T>, I<U>; } interface I4<T> : I1<T, T> { } interface I5<T> : I2<I<object>, T> { } interface I6<U> : I3<I<U>, I<U>> { }"; Action<ModuleSymbol> validator = module => { var method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I1").GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T", "U"); method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I2").GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T", "I<U>", "I<object>"); method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I3").GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "I<T>", "I<U>"); method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I4").Interfaces()[0].GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "T"); method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I5").Interfaces()[0].GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "I<object>", "I<T>"); method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I6").Interfaces()[0].GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "I<I<U>>"); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } /// <summary> /// Type argument violating duplicate constraint types /// should result in a single error, not multiple. /// </summary> [WorkItem(542620, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542620")] [Fact] public void DuplicateConstraintTypeViolations() { var source = @"interface I<T> { } class A<T, U> where U : T, I<U> { } class B<T> { internal static void M<U>() where U : T, I<object>, I<string> { } } class C { static void M<T1, T2>() where T2 : I<T1>, I<T2> { new A<I<object>, object>(); B<I<object>>.M<string>(); M<object, object>(); } }"; CreateCompilation(source).VerifyDiagnostics( // (11,26): error CS0311: The type 'object' cannot be used as type parameter 'U' in the generic type or method 'A<T, U>'. There is no implicit reference conversion from 'object' to 'I<object>'. // new A<I<object>, object>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "object").WithArguments("A<T, U>", "I<object>", "U", "object").WithLocation(11, 26), // (12,22): error CS0311: The type 'string' cannot be used as type parameter 'U' in the generic type or method 'B<I<object>>.M<U>()'. There is no implicit reference conversion from 'string' to 'I<object>'. // B<I<object>>.M<string>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<string>").WithArguments("B<I<object>>.M<U>()", "I<object>", "U", "string").WithLocation(12, 22), // (12,22): error CS0311: The type 'string' cannot be used as type parameter 'U' in the generic type or method 'B<I<object>>.M<U>()'. There is no implicit reference conversion from 'string' to 'I<string>'. // B<I<object>>.M<string>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<string>").WithArguments("B<I<object>>.M<U>()", "I<string>", "U", "string").WithLocation(12, 22), // (13,9): error CS0311: The type 'object' cannot be used as type parameter 'T2' in the generic type or method 'C.M<T1, T2>()'. There is no implicit reference conversion from 'object' to 'I<object>'. // M<object, object>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M<object, object>").WithArguments("C.M<T1, T2>()", "I<object>", "T2", "object").WithLocation(13, 9)); } [ClrOnlyFact] public void ContravariantInterfacesInConstraints() { var source = @" using System; using System.Collections.Generic; interface X<in T> { } interface _<in T> : X<T> { } class C { static void Goo<T>() where T : class, X<_<X<T>>> { Goo<X<_<X<X<_<X<X<X<_<X<_<X<T>>>>>>>>>>>>>(); } static void Main() { } } "; CompileAndVerify(source, expectedOutput: ""); } /// <summary> /// Redundant System.Object constraints should be removed /// and '.ctor' and System.ValueType constraints should be /// removed if 'valuetype' is specified. By contrast, redundant /// 'class' constraints should not be removed if explicit class /// constraint is specified. /// </summary> [WorkItem(543335, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543335")] [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void ObjectAndValueTypeMetadataConstraints() { var ilSource = @".class public A { } .class public O1<T> { } .class public O2<(object)T> { } .class public V1<valuetype T> { } .class public V2<valuetype .ctor T> { } .class public V3<valuetype ([mscorlib]System.ValueType) T> { } .class public V4<valuetype .ctor ([mscorlib]System.ValueType) T> { } .class public V5<([mscorlib]System.ValueType) T> { } .class public R1<(A) T> { } .class public R2<class (A) T> { }"; var csharpSource = ""; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); var @namespace = compilation.GlobalNamespace; CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("O1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("O2").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("V1").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("V2").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("V3").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("V4").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("V5").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "ValueType", "ValueType", "ValueType"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("R1").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "A", "A", "A"); CheckConstraints(@namespace.GetMember<NamedTypeSymbol>("R2").TypeParameters[0], TypeParameterConstraintKind.ReferenceType, false, true, "A", "A", "A"); } [WorkItem(543335, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543335")] [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void ObjectAndValueTypeMethodMetadataConstraints() { var ilSource = @".class public abstract A<T> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M1<(!T)U>() { } .method public abstract virtual instance void M2<valuetype (!T)U>() { } } .class public B0 extends class A<object> { .method public specialname rtspecialname instance void .ctor() { ret } .method public virtual instance void M1<U>() { ret } .method public virtual instance void M2<valuetype U>() { ret } } .class public B1 extends class A<object> { .method public specialname rtspecialname instance void .ctor() { ret } .method public virtual instance void M1<(object)U>() { ret } .method public virtual instance void M2<valuetype (object)U>() { ret } } .class public B2 extends class A<class [mscorlib]System.ValueType> { .method public specialname rtspecialname instance void .ctor() { ret } .method public virtual instance void M1<(class [mscorlib]System.ValueType)U>() { ret } .method public virtual instance void M2<valuetype (class [mscorlib]System.ValueType)U>() { ret } }"; var csharpSource = ""; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource); var @namespace = compilation.GlobalNamespace; var type = @namespace.GetMember<NamedTypeSymbol>("B0"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); type = @namespace.GetMember<NamedTypeSymbol>("B1"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); type = @namespace.GetMember<NamedTypeSymbol>("B2"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "ValueType", "ValueType", "ValueType"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); } /// <summary> /// Overriding methods with implicit and explicit /// System.Object and System.ValueType constraints. /// </summary> [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void OverridingObjectAndValueTypeMethodMetadataConstraints() { var ilSource = @".class interface public abstract IA { .method public abstract virtual instance void M1<U>() { } .method public abstract virtual instance void M2<(object)U>() { } } .class interface public abstract IB { .method public abstract virtual instance void M1<valuetype U>() { } .method public abstract virtual instance void M2<valuetype (object)U>() { } } .class interface public abstract IC { .method public abstract virtual instance void M1<valuetype U>() { } .method public abstract virtual instance void M2<valuetype (class [mscorlib]System.ValueType)U>() { } } .class public abstract A<T> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M1<(!T)U>() { } .method public abstract virtual instance void M2<(!T)U>() { } } .class public abstract A0 extends class A<object> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M1<U>() { } .method public abstract virtual instance void M2<(object)U>() { } } .class public abstract B<T> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M1<valuetype (!T)U>() { } .method public abstract virtual instance void M2<valuetype (!T)U>() { } } .class public abstract B0 extends class B<object> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M1<valuetype U>() { } .method public abstract virtual instance void M2<valuetype (object)U>() { } } .class public abstract C0 extends class B<class [mscorlib]System.ValueType> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M1<valuetype U>() { } .method public abstract virtual instance void M2<valuetype (class [mscorlib]System.ValueType)U>() { } }"; var csharpSource = @"class AImplicit : IA { public void M1<U>() { } public void M2<U>() { } } class AExplicit : IA { void IA.M1<U>() { } void IA.M2<U>() { } } class BImplicit : IB { public void M1<U>() where U : struct { } // Dev10 error public void M2<U>() where U : struct { } // Dev10 error } class BExplicit : IB { void IB.M1<U>() { } void IB.M2<U>() { } } class CImplicit : IC { public void M1<U>() where U : struct { } // Dev10 error public void M2<U>() where U : struct { } } class CExplicit : IC { void IC.M1<U>() { } void IC.M2<U>() { } } class A1 : A0 { public override void M1<U>() { } public override void M2<U>() { } } class B1 : B0 { public override void M1<U>() { } public override void M2<U>() { } } class C1 : C0 { public override void M1<U>() { } public override void M2<U>() { } }"; CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics(); } /// <summary> /// Object constraints should be dropped from TypeParameterSymbol.ConstraintTypes /// on import and type substitution. /// </summary> [WorkItem(543831, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543831")] [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void ObjectConstraintTypes() { var ilSource = @".class interface public abstract I<T> { .method public abstract virtual instance void M<(!T)U>() { } } .class interface public abstract I0 implements class I<object> { } .class public abstract A<T> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M<(!T)U>() { } } .class public abstract A1 extends class A<object> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M<U>() { } } .class public abstract A2 extends class A<object> { .method public specialname rtspecialname instance void .ctor() { ret } .method public abstract virtual instance void M<(object)U>() { } }"; var csharpSource = @"interface I1 : I<object> { } class B0 : A<object> { public override void M<U>() { } } class B1 : A1 { public override void M<U>() { } } class B2 : A2 { public override void M<U>() { } } class C0 : I0 { public void M<U>() { } } class C1 : I<object> { public void M<U>() { } } class C2 : I<object> { void I<object>.M<U>() { } } class D<T> { public void M<U>() where U : T { } } class D0 : D<object> { }"; var compilation = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource).VerifyDiagnostics(); var @namespace = compilation.GlobalNamespace; var type = @namespace.GetMember<NamedTypeSymbol>("I0"); CheckConstraints(type.Interfaces()[0].GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("A1"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("A2"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("I1"); CheckConstraints(type.Interfaces()[0].GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("B0"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("B1"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("B2"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("C0"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("C1"); CheckConstraints(type.GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("C2"); CheckConstraints(type.GetMethod("I<System.Object>.M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = @namespace.GetMember<NamedTypeSymbol>("D0"); CheckConstraints(type.BaseType().GetMember<MethodSymbol>("M").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); } /// <summary> /// Object constraint should not be emitted /// for compatibility with Dev10. /// </summary> [WorkItem(543710, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543710")] [ClrOnlyFact] public void EmittedObjectConstraint() { var source = @"class C { } interface I<T, U> where U : T { } interface I0<T> : I<object, T> { } interface I1<T> : I<C, T> where T : C { } abstract class A<T> { public abstract void M<U>() where U : T; } class A0 : A<object> { public override void M<U>() { } } class A1 : A<C> { public override void M<U>() { } }"; Action<ModuleSymbol> validator = module => { var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I0"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("I1"); CheckConstraints(type.TypeParameters[0], TypeParameterConstraintKind.None, false, true, "C", "C", "C"); var method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("A0").GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); method = module.GlobalNamespace.GetMember<NamedTypeSymbol>("A1").GetMember<MethodSymbol>("M"); CheckConstraints(method.TypeParameters[0], TypeParameterConstraintKind.None, false, true, "C", "C", "C"); }; CompileAndVerify( source: source, sourceSymbolValidator: validator, symbolValidator: validator); } [Fact] public void InheritedObjectConstraint() { var source = @"interface IA { } interface IB : IA { } class A : IA { } class B : A, IB { } abstract class C<T> { public abstract void M1<U>() where U : T; public abstract void M2<U>() where U : struct, T; } class C0 : C<object> { public override void M1<U>() { } public override void M2<U>() { } } class C1 : C<System.ValueType> { public override void M1<U>() { } public override void M2<U>() { } } abstract class D<T> { public abstract void M1<U>() where U : IA, T; public abstract void M2<U>() where U : IB, T; public abstract void M3<U>() where U : A, T; public abstract void M4<U>() where U : B, T; } class D0 : D<object> { public override void M1<U>() { } public override void M2<U>() { } public override void M3<U>() { } public override void M4<U>() { } } class D1 : D<IA> { public override void M1<U>() { } public override void M2<U>() { } public override void M3<U>() { } public override void M4<U>() { } } class D2 : D<A> { public override void M1<U>() { } public override void M2<U>() { } public override void M3<U>() { } public override void M4<U>() { } }"; var compilation = CreateCompilation(source); var @namespace = compilation.GlobalNamespace; var type = @namespace.GetMember<NamedTypeSymbol>("C0"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType"); type = @namespace.GetMember<NamedTypeSymbol>("C1"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "ValueType", "ValueType", "ValueType"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.ValueType, true, false, "ValueType", "ValueType", "ValueType"); type = @namespace.GetMember<NamedTypeSymbol>("D0"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "IA"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "IB"); CheckConstraints(type.GetMember<MethodSymbol>("M3").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "A", "A", "A"); CheckConstraints(type.GetMember<MethodSymbol>("M4").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "B", "B", "B"); type = @namespace.GetMember<NamedTypeSymbol>("D1"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "IA"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.None, false, false, "object", "object", "IB", "IA"); CheckConstraints(type.GetMember<MethodSymbol>("M3").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "A", "A", "A", "IA"); CheckConstraints(type.GetMember<MethodSymbol>("M4").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "B", "B", "B", "IA"); type = @namespace.GetMember<NamedTypeSymbol>("D2"); CheckConstraints(type.GetMember<MethodSymbol>("M1").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "A", "A", "IA", "A"); CheckConstraints(type.GetMember<MethodSymbol>("M2").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "A", "A", "IB", "A"); CheckConstraints(type.GetMember<MethodSymbol>("M3").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "A", "A", "A"); CheckConstraints(type.GetMember<MethodSymbol>("M4").TypeParameters[0], TypeParameterConstraintKind.None, false, true, "B", "B", "B", "A"); } [WorkItem(545410, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545410")] [Fact] public void InheritedValueConstraintForNullable1() { var source = @" class A { public virtual T? Goo<T>() where T : struct { return null; } } class B : A { public override T? Goo<T>() { return null; } } "; CreateCompilation(source, options: TestOptions.ReleaseDll).VerifyDiagnostics(); } [WorkItem(545410, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545410")] [Fact] public void InheritedValueConstraintForNullable2() { var source = @" class A { public virtual T? Goo<T>() { return null; } } class B : A { public override T? Goo<T>() { return null; } } "; CreateCompilation(source, parseOptions: TestOptions.Regular9).VerifyDiagnostics( // (4,21): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // public virtual T? Goo<T>() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 21), // (12,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // public override T? Goo<T>() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(12, 22), // (12,24): error CS0508: 'B.Goo<T>()': return type must be 'T' to match overridden member 'A.Goo<T>()' // public override T? Goo<T>() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "Goo").WithArguments("B.Goo<T>()", "A.Goo<T>()", "T").WithLocation(12, 24), // (12,24): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>' // public override T? Goo<T>() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Goo").WithArguments("System.Nullable<T>", "T", "T").WithLocation(12, 24), // (6,16): error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead. // return null; Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(6, 16)); } [WorkItem(543710, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543710")] [ClrOnlyFact] public void InheritedObjectConstraint2() { var csCompilation = CreateCSharpCompilation("InheritedObjectConstraint2CS", @"using System; public abstract class Base1<T> { public virtual void Goo<G>(G d) where G : struct, T { Console.WriteLine(""Base1""); } } public class Base2 : Base1<Object> { public override void Goo<G>(G d) { Console.WriteLine(""Base2""); } }", compilationOptions: TestOptions.DebugDll); var csVerifier = CompileAndVerify(csCompilation); csVerifier.VerifyDiagnostics(); var vbCompilation = CreateVisualBasicCompilation("InheritedObjectConstraint2VB", @"Imports System Class Derived : Inherits Base2 Public Overrides Sub Goo(Of G As Structure)(ByVal d As G) Console.WriteLine(""Derived"") End Sub End Class Module Program Sub Main Dim x As Base1(Of Object) = New Derived x.Goo(1) End Sub End Module", compilationOptions: new Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions(OutputKind.ConsoleApplication), referencedCompilations: new[] { csCompilation }); vbCompilation.VerifyDiagnostics(); } private static void CheckConstraints( TypeParameterSymbol typeParameter, TypeParameterConstraintKind constraints, bool isValueType, bool isReferenceType, string effectiveBaseClassDescription, string deducedBaseTypeDescription, params string[] constraintTypeDescriptions) { Assert.Equal(constraints, Utils.GetTypeParameterConstraints(typeParameter)); Assert.Equal(typeParameter.IsValueType, isValueType); Assert.Equal(typeParameter.IsReferenceType, isReferenceType); Assert.Null(typeParameter.BaseType()); Assert.Equal(0, typeParameter.Interfaces().Length); Utils.CheckSymbol(typeParameter.EffectiveBaseClassNoUseSiteDiagnostics, effectiveBaseClassDescription); Utils.CheckSymbol(typeParameter.DeducedBaseTypeNoUseSiteDiagnostics, deducedBaseTypeDescription); Utils.CheckSymbols(typeParameter.ConstraintTypes(), constraintTypeDescriptions); } [WorkItem(545327, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545327")] [Fact] public void MissingObjectType() { var source = @"class A { } class B<T> where T : A { }"; CreateEmptyCompilation(source).VerifyDiagnostics( // (1,7): error CS0518: Predefined type 'System.Object' is not defined or imported // class A { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "A").WithArguments("System.Object").WithLocation(1, 7), // (2,7): error CS0518: Predefined type 'System.Object' is not defined or imported // class B<T> where T : A { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "B").WithArguments("System.Object").WithLocation(2, 7), // (2,7): error CS1729: 'object' does not contain a constructor that takes 0 arguments // class B<T> where T : A { } Diagnostic(ErrorCode.ERR_BadCtorArgCount, "B").WithArguments("object", "0").WithLocation(2, 7), // (1,7): error CS1729: 'object' does not contain a constructor that takes 0 arguments // class A { } Diagnostic(ErrorCode.ERR_BadCtorArgCount, "A").WithArguments("object", "0").WithLocation(1, 7)); } [Fact] public void MissingValueType() { var source = @"struct S { } abstract class A<T> { internal abstract void M<U>() where U : struct, T; } class B : A<S> { internal override void M<U>() { } }"; CreateEmptyCompilation(source).VerifyDiagnostics( // (2,16): error CS0518: Predefined type 'System.Object' is not defined or imported // abstract class A<T> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "A").WithArguments("System.Object").WithLocation(2, 16), // (1,8): error CS0518: Predefined type 'System.ValueType' is not defined or imported // struct S { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "S").WithArguments("System.ValueType").WithLocation(1, 8), // (4,23): error CS0518: Predefined type 'System.Void' is not defined or imported // internal abstract void M<U>() where U : struct, T; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "void").WithArguments("System.Void").WithLocation(4, 23), // (8,23): error CS0518: Predefined type 'System.Void' is not defined or imported // internal override void M<U>() { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "void").WithArguments("System.Void").WithLocation(8, 23), // (2,16): error CS1729: 'object' does not contain a constructor that takes 0 arguments // abstract class A<T> Diagnostic(ErrorCode.ERR_BadCtorArgCount, "A").WithArguments("object", "0").WithLocation(2, 16), // (6,7): error CS0518: Predefined type 'System.Void' is not defined or imported // class B : A<S> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "B").WithArguments("System.Void").WithLocation(6, 7)); } [Fact, WorkItem(11243, "DevDiv_Projects/Roslyn")] public void ConstraintGenericForPoint() { var source = @" class A { public interface I { } } class F<T> : A where T : F<object*>.I { } class G<T> : A where T : G<void*>.I { } class @c { static void Main() { } } "; // NOTE: we don't report that object* and void* are invalid type arguments, since validation // is performed on A.I, not on F<object*>.I or G<void*>.I. CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(); } [Fact, WorkItem(11243, "DevDiv_Projects/Roslyn")] public void ConstraintGenericForPoint_WithUnsafeContext() { var source = @" class A { public interface I { } } unsafe class F<T> : A where T : F<object*>.I { } unsafe class G<T> : A where T : G<void*>.I { } class @c { static void Main() { } } "; CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics( // (6,14): error CS0227: Unsafe code may only appear if compiling with /unsafe // unsafe class F<T> : A where T : F<object*>.I Diagnostic(ErrorCode.ERR_IllegalUnsafe, "F").WithLocation(6, 14), // (10,14): error CS0227: Unsafe code may only appear if compiling with /unsafe // unsafe class G<T> : A where T : G<void*>.I Diagnostic(ErrorCode.ERR_IllegalUnsafe, "G").WithLocation(10, 14)); CreateCompilation(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12).VerifyDiagnostics(); } [WorkItem(545460, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545460")] [Fact] public void TypeConstrainedToLambda() { var source = @"abstract class A<T> { public abstract void M<U>(U u) where U : () => T; } class B : A<int> { public override void M<U>(U u) { } }"; var compilation = CreateCompilation(source); Assert.NotEmpty(compilation.GetDiagnostics()); } [WorkItem(545460, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545460")] [Fact] public void TypeConstrainedToErrorType() { var source = @"abstract class A<T> { public abstract void M<U>(U u) where U : X, T; } class B : A<int> { public override void M<U>(U u) { } }"; CreateCompilation(source).VerifyDiagnostics( // (3,46): error CS0246: The type or namespace name 'X' could not be found (are you missing a using directive or an assembly reference?) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "X").WithArguments("X").WithLocation(3, 46)); } [WorkItem(545588, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545588")] [Fact] public void SatisfyOwnConstraints01() { var source = @"struct S { } enum E { } class A<T> { internal virtual void M<U>() where U : T { } } class B1 : A<int> { internal override void M<U>() { base.M<U>(); } } class B2 : A<S> { internal override void M<U>() { base.M<U>(); } } class B3 : A<E> { internal override void M<U>() { base.M<U>(); } } class B4 : A<int?> { internal override void M<U>() { base.M<U>(); } } class B5 : A<object[]> { internal override void M<U>() { base.M<U>(); } }"; CreateCompilation(source).VerifyDiagnostics(); } [WorkItem(545588, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545588")] [Fact] public void SatisfyOwnConstraints02() { var source = @"class A<T1, T2> { internal virtual void M0<U>() where U : T1, T2 { } internal virtual void M1<U>() where U : T1 { } internal virtual void M2<U>() where U : T2 { } } class B : A<int, object> { internal override void M0<U>() { base.M0<U>(); base.M1<U>(); base.M2<U>(); } internal override void M1<U>() { base.M0<U>(); base.M1<U>(); base.M2<U>(); } internal override void M2<U>() { base.M0<U>(); base.M1<U>(); base.M2<U>(); } }"; CreateCompilation(source).VerifyDiagnostics( // (23,14): error CS0314: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A<int, object>.M0<U>()'. There is no boxing conversion or type parameter conversion from 'U' to 'int'. // base.M0<U>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "M0<U>").WithArguments("A<int, object>.M0<U>()", "int", "U", "U").WithLocation(23, 14), // (24,14): error CS0314: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A<int, object>.M1<U>()'. There is no boxing conversion or type parameter conversion from 'U' to 'int'. // base.M1<U>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "M1<U>").WithArguments("A<int, object>.M1<U>()", "int", "U", "U").WithLocation(24, 14)); } [WorkItem(545588, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545588")] [Fact] public void SatisfyOwnConstraints03() { var source = @"class A<T> { internal virtual void M1<U, V>() where U : T where V : U { } internal virtual void M2<U>() where U : T { } } class B : A<object[]> { internal override void M1<U, V>() { base.M1<U, U>(); base.M1<U, V>(); base.M1<V, U>(); base.M1<V, V>(); base.M2<U>(); base.M2<V>(); } }"; CreateCompilation(source).VerifyDiagnostics( // (12,14): error CS0311: The type 'U' cannot be used as type parameter 'V' in the generic type or method 'A<object[]>.M1<U, V>()'. There is no implicit reference conversion from 'U' to 'V'. // base.M1<V, U>(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M1<V, U>").WithArguments("A<object[]>.M1<U, V>()", "V", "V", "U").WithLocation(12, 14)); } [Fact] public void ExtensionMethodOnArrayInterface() { var source = @"using System.Collections; using System.Collections.Generic; abstract class A<T> { internal abstract void M<U>(U o) where U : T; internal static void M1(IEnumerable o) { } internal static void M2(IEnumerable<object> o) { } internal T F() { return default(T); } } class B : A<object[]> { internal override void M<U>(U o) { M1(o); M2(o); M1(F()); M2(F()); o.E1(); o.E2(); F().E1(); F().E2(); } } static class M { internal static void E1(this IEnumerable o) { } internal static void E2(this IEnumerable<object> o) { } }"; CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics( // (15,12): error CS1503: Argument 1: cannot convert from 'U' to 'System.Collections.Generic.IEnumerable<object>' // M2(o); Diagnostic(ErrorCode.ERR_BadArgType, "o").WithArguments("1", "U", "System.Collections.Generic.IEnumerable<object>"), // (19,9): error CS1929: 'U' does not contain a definition for 'E2' and the best extension method overload 'M.E2(System.Collections.Generic.IEnumerable<object>)' requires a receiver of type 'System.Collections.Generic.IEnumerable<object>' // o.E2(); Diagnostic(ErrorCode.ERR_BadInstanceArgType, "o").WithArguments("U", "E2", "M.E2(System.Collections.Generic.IEnumerable<object>)", "System.Collections.Generic.IEnumerable<object>") ); } /// <summary> /// Constraint failures on derived type when referencing members of /// base type. Dev11 does not report errors on such constraint failures /// for base type, interfaces, or method signatures. /// </summary> [Fact] public void MembersOfBaseTypeConstraintViolationOnDerived() { var source = @"class A { internal class B { } internal interface I { } internal static object F = null; } class C<T> : A where T : struct { } class C1 { } class C2 { } class C3 { } class C4 { } class C5 { } class C6 { } class D : C<C1>.B, C<C2>.I { } // Dev11: no errors class E { static C<C3>.B M1(C<C4>.B o) // Dev11: no errors { return null; } static void M2() { object o; o = new C<C5>.B(); o = C<C6>.F; } }"; CreateCompilation(source).VerifyDiagnostics( // (24,19): error CS0453: The type 'C5' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C5").WithArguments("C<T>", "T", "C5").WithLocation(24, 19), // (25,15): error CS0453: The type 'C6' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C<T>' Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "C6").WithArguments("C<T>", "T", "C6").WithLocation(25, 15)); } /// <summary> /// Cycle with field types with new() constraint. /// </summary> [WorkItem(546394, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546394")] [Fact] public void HasPublicParameterlessConstructorCycle01() { var source = @"class A { C<B> F; } class B { C<A> F; } class C<T> where T : new() { }"; CreateCompilation(source).VerifyDiagnostics( // (3,10): warning CS0169: The field 'A.F' is never used Diagnostic(ErrorCode.WRN_UnreferencedField, "F").WithArguments("A.F").WithLocation(3, 10), // (7,10): warning CS0169: The field 'B.F' is never used Diagnostic(ErrorCode.WRN_UnreferencedField, "F").WithArguments("B.F").WithLocation(7, 10)); } /// <summary> /// Cycle with event types with new() constraint. /// </summary> [WorkItem(546394, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546394")] [Fact] public void HasPublicParameterlessConstructorCycle02() { var source = @"class A { event D<B> E; } class B { private B() { } event D<A> E; } class C { private C() { } event D<C> E { add { } remove { } } } delegate D<T> D<T>() where T : new();"; CreateCompilation(source).VerifyDiagnostics( // (3,13): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'D<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "E").WithArguments("D<T>", "T", "B").WithLocation(3, 16), // (13,16): error CS0310: 'C' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'D<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "E").WithArguments("D<T>", "T", "C").WithLocation(13, 16), // (8,16): warning CS0067: The event 'B.E' is never used // event D<A> E; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("B.E"), // (3,16): warning CS0067: The event 'A.E' is never used // event D<B> E; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("A.E")); } /// <summary> /// Cycle with field-like event type with new() constraint /// where field type is determined by an initializer. /// </summary> [WorkItem(546394, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546394")] [Fact] public void HasPublicParameterlessConstructorCycle03() { var source = @"class A { event D<object> E2 = new D<B>(() => { }); } class B { private B() { } event D<object> E1 = new D<A>(() => { }); } delegate void D<out T>() where T : new();"; CreateCompilation(source).VerifyDiagnostics( // (3,32): error CS0310: 'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'D<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "B").WithArguments("D<T>", "T", "B").WithLocation(3, 32)); } /// <summary> /// Cycle with event type with new() constraint where /// the event is an explicit implementation. /// </summary> [WorkItem(546394, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546394")] [Fact] public void HasPublicParameterlessConstructorCycle04() { var source = @"delegate D<T> D<T>(); interface I<T> where T : new() { event D<T> E; } class C : I<C> { private C() { } event D<C> I<C>.E { add { } remove { } } }"; CreateCompilation(source).VerifyDiagnostics( // (6,7): error CS0310: 'C' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "C").WithArguments("I<T>", "T", "C").WithLocation(6, 7), // (9,16): error CS0310: 'C' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'I<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "I<C>").WithArguments("I<T>", "T", "C").WithLocation(9, 16)); } /// <summary> /// Cycle with property types with new() constraint. /// </summary> [WorkItem(546394, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546394")] [Fact] public void HasPublicParameterlessConstructorCycle05() { var source = @"class A { C<B> P { get; set; } } class B { C<A> P { get; set; } } class C<T> where T : new() { }"; CreateCompilation(source).VerifyDiagnostics(); } /// <summary> /// Cycle with property types with new() constraint where the types /// are parameter types and properties are explicit implementations. /// </summary> [WorkItem(546394, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546394")] [Fact] public void HasPublicParameterlessConstructorCycle06() { var source = @"interface IA<T> where T : new() { IA<T> P { get; } } interface IB<T> where T : new() { object this[IB<T> i] { get; } } class A1 : IA<A1> { private A1() { } IA<A1> IA<A1>.P { get { return null; } } } class A2 : IA<A2> { private A2() { } public IA<A2> P { get { return null; } } } class B1 : IB<B1> { private B1() { } object IB<B1>.this[IB<B1> i] { get { return null; } } } class B2 : IB<B2> { private B2() { } public object this[IB<B2> i] { get { return null; } } }"; CreateCompilation(source).VerifyDiagnostics( // (24,7): error CS0310: 'B2' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IB<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "B2").WithArguments("IB<T>", "T", "B2").WithLocation(24, 7), // (14,7): error CS0310: 'A2' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IA<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "A2").WithArguments("IA<T>", "T", "A2").WithLocation(14, 7), // (9,7): error CS0310: 'A1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IA<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "A1").WithArguments("IA<T>", "T", "A1").WithLocation(9, 7), // (19,7): error CS0310: 'B1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IB<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "B1").WithArguments("IB<T>", "T", "B1").WithLocation(19, 7), // (22,12): error CS0310: 'B1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IB<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "IB<B1>").WithArguments("IB<T>", "T", "B1").WithLocation(22, 12), // (22,31): error CS0310: 'B1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IB<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "i").WithArguments("IB<T>", "T", "B1").WithLocation(22, 31), // (12,12): error CS0310: 'A1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IA<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "IA<A1>").WithArguments("IA<T>", "T", "A1").WithLocation(12, 12), // (12,19): error CS0310: 'A1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IA<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "P").WithArguments("IA<T>", "T", "A1").WithLocation(12, 19), // (17,19): error CS0310: 'A2' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IA<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "P").WithArguments("IA<T>", "T", "A2").WithLocation(17, 19), // (27,31): error CS0310: 'B2' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IB<T>' Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "i").WithArguments("IB<T>", "T", "B2").WithLocation(27, 31)); } [WorkItem(546780, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546780")] [Fact] public void Bug16806() { var source = @"class A<T> { class B<U> : A<object> { class C : B<> { } object F = typeof(B<>); } }"; CreateCompilation(source).VerifyDiagnostics( // (5,19): error CS7003: Unexpected use of an unbound generic name Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "B<>").WithLocation(5, 19)); } [WorkItem(546972, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546972")] [Fact] public void Bug17407() { var source = @" public class Test { public static void Main() { } } // TEST 1 public class GClass<T, U> where T : U where U : class { } public class Test1 { public static void RunTest() { new GClass<int?, object>(); } } // TEST 2 public class GNew<T, U> where T : U where U : new() { } public class Test2 { public static void RunTest() { new GNew<int?, object>(); } }"; CreateCompilation(source).VerifyDiagnostics(); } [WorkItem(531227, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531227")] [Fact] public void ConstraintOverrideBaseTypeCycle() { var text = @" public class Base<T> where T : new() { public virtual int P { get; set; } } public class Derived : Base<Derived> { public override int P { get; set; } } "; var comp = CreateCompilation(text); var derivedType = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Derived"); derivedType.GetMembers(); } [WorkItem(531227, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531227")] [Fact] public void ConstraintExplicitImplementationInterfaceCycle() { var text = @" public interface Interface<T> where T : new() { int P { get; set; } } public class Implementation : Interface<Implementation> { int Interface<Implementation>.P { get; set; } } "; var comp = CreateCompilation(text); var implementingType = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Implementation"); implementingType.GetMembers(); } [WorkItem(546973, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546973")] [Fact] public void AllowBadConstraintsInMetadata() { var ilSource = @".assembly extern mscorlib { .ver 0:0:0:0 } .assembly '<<GeneratedFileName>>' { .ver 0:0:0:0 } .class public auto ansi beforefieldinit GStruct`2<(!U) T,valuetype U> extends [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 7 (0x7) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ret } // end of method GStruct`2::.ctor } // end of class GStruct`2 "; var source = @" public interface I { } public struct S : I { } public class Test5 { public static void RunTest() { GStruct<S, S> obj14 = new GStruct<S, S>(); GStruct<int, int> obj15 = new GStruct<int, int>(); } }"; CreateCompilationWithILAndMscorlib40(source, ilSource, appendDefaultHeader: false).VerifyDiagnostics(); } [WorkItem(531630, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531630")] [Fact] public void CheckConstraintOnArrayTypeArgument() { var source = @" public struct S { E?[] eNullableArr; public void DoSomething<T>(T t) { } public void Test() { DoSomething(this.eNullableArr); } } public class E { } "; CreateCompilation(source).VerifyDiagnostics( // (4,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // E?[] eNullableArr; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 6), // (4,10): warning CS0649: Field 'S.eNullableArr' is never assigned to, and will always have its default value null // E?[] eNullableArr; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "eNullableArr").WithArguments("S.eNullableArr", "null").WithLocation(4, 10)); } [WorkItem(575455, "DevDiv")] [Fact] public void UseSiteErrorReportingCycleInBaseReference() { var source1 = @"public class A { } public interface IA { }"; var compilation1 = CreateCompilation(source1, assemblyName: "e521fe98-c881-45cf-8870-249e00ae400d"); compilation1.VerifyDiagnostics(); var source2 = @"public class B : A { } public class C<T> : B where T : B { } public interface IB : IA { } public interface IC<T> : IB where T : IB { }"; var compilation2 = CreateCompilation(source2, references: new MetadataReference[] { new CSharpCompilationReference(compilation1) }); compilation2.VerifyDiagnostics(); var source3 = @"class D : C<D>, IC<D> { }"; var compilation3 = CreateCompilation(source3, references: new MetadataReference[] { new CSharpCompilationReference(compilation2) }); compilation3.VerifyDiagnostics( // (1,11): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // class D : C<D>, IC<D> { } Diagnostic(ErrorCode.ERR_NoTypeDef, "C<D>").WithArguments("A", "e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 11), // (1,7): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // class D : C<D>, IC<D> { } Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("IA", "e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"), // (1,7): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly 'e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // class D : C<D>, IC<D> { } Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("A", "e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"), // (1,7): error CS0012: The type 'IA' is defined in an assembly that is not referenced. You must add a reference to assembly 'e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // class D : C<D>, IC<D> { } Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("IA", "e521fe98-c881-45cf-8870-249e00ae400d, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 7)); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/577251")] public void Bug577251() { var source = @"interface IA<T> { } interface IB { void F<T>() where T : IA<C<int>.E*[]>; } class C<T> { public enum E { } public void F<U>() where U : IA<E*[]> { } } class D : C<int>, IB { }"; CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(); CreateCompilation(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12).VerifyDiagnostics( // (4,30): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // void F<T>() where T : IA<C<int>.E*[]>; Diagnostic(ErrorCode.ERR_UnsafeNeeded, "C<int>.E*").WithLocation(4, 30), // (9,37): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // public void F<U>() where U : IA<E*[]> { } Diagnostic(ErrorCode.ERR_UnsafeNeeded, "E*").WithLocation(9, 37)); source = @"interface IA<T> { } interface IB { void F<T, U>() where T : IA<C<U>.E*[]>; } class C<T> { public enum E { } public void F<U, V>() where U : IA<C<V>.E*[]> { } } class D<T> : C<T>, IB { }"; CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(); CreateCompilation(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12).VerifyDiagnostics( // (4,33): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // void F<T, U>() where T : IA<C<U>.E*[]>; Diagnostic(ErrorCode.ERR_UnsafeNeeded, "C<U>.E*").WithLocation(4, 33), // (9,40): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // public void F<U, V>() where U : IA<C<V>.E*[]> { } Diagnostic(ErrorCode.ERR_UnsafeNeeded, "C<V>.E*").WithLocation(9, 40)); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/577251")] public void Bug577251_UnsafeContext() { var source = @"interface IA<T> { } unsafe interface IB { void F<T>() where T : IA<C<int>.E*[]>; } unsafe class C<T> { public enum E { } public void F<U>() where U : IA<E*[]> { } } class D : C<int>, IB { }"; CreateCompilation(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12).VerifyDiagnostics(); source = @"interface IA<T> { } unsafe interface IB { void F<T, U>() where T : IA<C<U>.E*[]>; } unsafe class C<T> { public enum E { } public void F<U, V>() where U : IA<C<V>.E*[]> { } } class D<T> : C<T>, IB { }"; CreateCompilation(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12).VerifyDiagnostics(); } [WorkItem(578350, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578350")] [Fact] public void Bug578350() { var source = @"class C<T> { } interface I { void F<T>() where T : C<object>; } abstract class A<T> { public virtual void F<U>() where U : C<T> { } } class B0 : A<object>, I { } // Dev11: CS0425: 'The constraints for type parameter 'U' of method 'A<dynamic>.F<U>()' must match ...' class B1 : A<dynamic>, I { } // Dev11: No error class B2 : A<dynamic>, I { public override void F<T>() { } }"; CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(); } [WorkItem(654522, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/654522")] [ClrOnlyFact] public void Bug654522() { var compilation = CreateCompilationWithMscorlib40AndSystemCore("public interface I<W> where W : struct {}").VerifyDiagnostics(); Action<ModuleSymbol> metadataValidator = delegate (ModuleSymbol module) { var metadata = ((PEModuleSymbol)module).Module; var typeI = (PENamedTypeSymbol)module.GlobalNamespace.GetTypeMembers("I").Single(); Assert.Equal(1, typeI.TypeParameters.Length); var tp = (PETypeParameterSymbol)typeI.TypeParameters[0]; string name; GenericParameterAttributes flags; metadata.GetGenericParamPropsOrThrow(tp.Handle, out name, out flags); Assert.Equal(GenericParameterAttributes.DefaultConstructorConstraint, flags & GenericParameterAttributes.DefaultConstructorConstraint); var metadataReader = metadata.MetadataReader; var constraints = metadataReader.GetGenericParameter(tp.Handle).GetConstraints(); Assert.Equal(1, constraints.Count); var tokenDecoder = new MetadataDecoder((PEModuleSymbol)module, typeI); var constraintTypeHandle = metadataReader.GetGenericParameterConstraint(constraints[0]).Type; TypeSymbol typeSymbol = tokenDecoder.GetTypeOfToken(constraintTypeHandle); Assert.Equal(SpecialType.System_ValueType, typeSymbol.SpecialType); }; CompileAndVerify(compilation, symbolValidator: metadataValidator); } [Fact] public void Bug578762() { var source = @"interface IA<T> { } interface IB<T> : IA<T> { } interface IC<T> : IB<T> { } static class M { internal static void E1<T>(this IA<T> o) { } internal static void E2<T>(this IB<T> o) { } internal static void E3<T>(this IC<T> o) { } } class C { static void F<T>(T o) where T : IA<string>, IC<string>, IB<string> { o.E1(); o.E2(); o.E3(); } }"; CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(); source = @"class A<T> { } class B<T> : A<T> { } class C<T> : B<T> { } static class M { internal static void E1<T>(this A<T> o) { } internal static void E2<T>(this B<T> o) { } internal static void E3<T>(this C<T> o) { } } abstract class D<T, U, V> { internal abstract void F<X>(X o) where X : T, U, V; } class E : D<A<string>, C<string>, B<string>> { internal override void F<X>(X o) { o.E1(); o.E2(); o.E3(); } }"; CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(); source = @"interface IA<T> { } class A<T> : IA<T> { } class B<T> : A<T>, IA<object> { } static class M { internal static void E0(this IA<object> o) { } internal static void E1<T>(this IA<T> o) { } } abstract class C<T, U> { internal abstract void F<X>(X o) where X : T, U; } class D1 : C<A<string>, B<string>> { internal override void F<X>(X o) { o.E0(); o.E1(); } } class D2 : C<B<object>, A<object>> { internal override void F<X>(X o) { o.E0(); o.E1(); } }"; CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics( // (18,11): error CS0411: The type arguments for method 'M.E1<T>(IA<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // o.E1(); Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "E1").WithArguments("M.E1<T>(IA<T>)").WithLocation(18, 11)); } [Fact] public void AccessProtectedMemberOnInstance_1() { var source = @"delegate void D(); class A { protected object F = 1; protected object G() { return null; } protected object P { get; set; } protected object this[int index] { get { return null; } set { } } protected event D E; } class B<T> : A where T : A { static void M(T t) { object o; o = t.F; o = t.G(); o = t.P; t.P = o; o = t[1]; t[2] = o; t.E += null; } }"; CreateCompilation(source).VerifyDiagnostics( // (15,15): error CS1540: Cannot access protected member 'A.F' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // o = t.F; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "F").WithArguments("A.F", "A", "B<T>"), // (16,15): error CS1540: Cannot access protected member 'A.G()' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // o = t.G(); Diagnostic(ErrorCode.ERR_BadProtectedAccess, "G").WithArguments("A.G()", "A", "B<T>"), // (17,15): error CS1540: Cannot access protected member 'A.P' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // o = t.P; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "P").WithArguments("A.P", "A", "B<T>"), // (18,11): error CS1540: Cannot access protected member 'A.P' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // t.P = o; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "P").WithArguments("A.P", "A", "B<T>"), // (19,13): error CS1540: Cannot access protected member 'A.this[int]' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // o = t[1]; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "t[1]").WithArguments("A.this[int]", "A", "B<T>"), // (20,9): error CS1540: Cannot access protected member 'A.this[int]' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // t[2] = o; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "t[2]").WithArguments("A.this[int]", "A", "B<T>"), // (21,11): error CS1540: Cannot access protected member 'A.E' via a qualifier of type 'A'; the qualifier must be of type 'B<T>' (or derived from it) // t.E += null; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "E").WithArguments("A.E", "A", "B<T>"), // (8,23): warning CS0067: The event 'A.E' is never used // protected event D E; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("A.E")); } [WorkItem(746999, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/746999")] [Fact] public void AccessProtectedMemberOnInstance_2() { var source = @"delegate void D(); class A { protected object F = 1; protected object G() { return null; } protected object P { get; set; } protected object this[int index] { get { return null; } set { } } protected event D E; } class B<T> : A where T : B<T> { static void M(T t) { object o; o = t.F; o = t.G(); o = t.P; t.P = o; o = t[1]; t[2] = o; t.E += null; } }"; CreateCompilation(source).VerifyDiagnostics( // (8,23): warning CS0067: The event 'A.E' is never used // protected event D E; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("A.E")); } [WorkItem(746999, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/746999")] [Fact] public void AccessProtectedMemberOnInstance_3() { var source = @"class A { protected object F = 1; protected object P { get { return null; } } } class B : A { class C1<T, U, V> where T : A where U : B where V : T, U { static void M(T t, U u, V v) { object o; o = t.F; o = t.P; o = u.F; o = u.P; o = v.F; o = v.P; } } }"; CreateCompilation(source).VerifyDiagnostics( // (16,19): error CS1540: Cannot access protected member 'A.F' via a qualifier of type 'A'; the qualifier must be of type 'B.C1<T, U, V>' (or derived from it) // o = t.F; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "F").WithArguments("A.F", "A", "B.C1<T, U, V>"), // (17,19): error CS1540: Cannot access protected member 'A.P' via a qualifier of type 'A'; the qualifier must be of type 'B.C1<T, U, V>' (or derived from it) // o = t.P; Diagnostic(ErrorCode.ERR_BadProtectedAccess, "P").WithArguments("A.P", "A", "B.C1<T, U, V>")); } [WorkItem(767334, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/767334")] [ClrOnlyFact] public void ConstraintOnSynthesizedExplicitImplementationMethod() { var source1 = @"public interface I0 { void M<T>() where T : A; } public interface I1<T> { void M<U>() where U : T; } public class A { } public class B0 { public void M<T>() { } } public class B<T> { public void M<U>() where U : T { } public interface I2<U> { void M<V>() where V : T, U; } }"; var compilation1 = CreateCompilation(source1); compilation1.VerifyDiagnostics(); var source2 = @"class C0 : B0, I1<object> { } class C1 : B<A>, I0 { } class C2 : B<A>, I1<A> { } class C3 : B0, B<object>.I2<object> { } class C4 : B<A>, B<object>.I2<A> { } class C<T> : B<T>, B<object>.I2<T> { } class P { static void Main() { System.Console.WriteLine(new C0()); System.Console.WriteLine(new C1()); System.Console.WriteLine(new C2()); System.Console.WriteLine(new C3()); System.Console.WriteLine(new C4()); System.Console.WriteLine(new C<A>()); } }"; var compilation2 = CreateCompilation( source2, references: new MetadataReference[] { MetadataReference.CreateFromImage(compilation1.EmitToArray()) }, options: TestOptions.ReleaseExe); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: @"C0 C1 C2 C3 C4 C`1[A]"); } [WorkItem(837422, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/837422")] [ClrOnlyFact] public void RedundantValueTypeConstraint() { var source = @"using System; interface I<T> { void M<U>() where U : struct, T; } abstract class A<T> { internal abstract void M<U>() where U : struct, T; } class B : A<ValueType>, I<ValueType> { internal override void M<T>() { } void I<ValueType>.M<T>() { } }"; CompileAndVerify(source); } [WorkItem(4097, "https://github.com/dotnet/roslyn/issues/4097")] [Fact] public void ObsoleteTypeInConstraints() { var source = @" [System.Obsolete] class Class1<T> where T : Class2 { } [System.Obsolete] class Class2 { } class Class3<T> where T : Class2 { [System.Obsolete] void M1<S>() where S : Class2 {} void M2<S>() where S : Class2 {} } partial class Class4 { [System.Obsolete] partial void M3<S>() where S : Class2; } partial class Class4 { partial void M4<S>() where S : Class2; } "; CompileAndVerify(source, options: TestOptions.DebugDll).VerifyDiagnostics( // (12,27): warning CS0612: 'Class2' is obsolete // class Class3<T> where T : Class2 Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Class2").WithArguments("Class2").WithLocation(12, 27), // (18,28): warning CS0612: 'Class2' is obsolete // void M2<S>() where S : Class2 Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Class2").WithArguments("Class2").WithLocation(18, 28), // (30,36): warning CS0612: 'Class2' is obsolete // partial void M4<S>() where S : Class2; Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Class2").WithArguments("Class2").WithLocation(30, 36) ); } [Fact, WorkItem("https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=278264")] public void IntPointerConstraintIntroducedBySubstitution() { string source = @" class R1<T1> { public virtual void f<T2>() where T2 : T1 { } } class R2 : R1<int*> { public override void f<T2>() { } } class Program { static void Main(string[] args) { R2 r = new R2(); r.f<int>(); } }"; var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular11); compilation.VerifyDiagnostics( // (6,7): error CS0306: The type 'int*' may not be used as a type argument // class R2 : R1<int *> Diagnostic(ErrorCode.ERR_BadTypeArgument, "R2").WithArguments("int*").WithLocation(6, 7) ); compilation = CreateCompilation(source, parseOptions: TestOptions.Regular12); compilation.VerifyDiagnostics( // (6,7): error CS0306: The type 'int*' may not be used as a type argument // class R2 : R1<int*> Diagnostic(ErrorCode.ERR_BadTypeArgument, "R2").WithArguments("int*").WithLocation(6, 7), // (6,15): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // class R2 : R1<int*> Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(6, 15)); } [Fact, WorkItem("https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=278264")] public void IntPointerConstraintIntroducedBySubstitution_UnsafeContext() { string source = @" class R1<T1> { public virtual void f<T2>() where T2 : T1 { } } unsafe class R2 : R1<int*> { public override void f<T2>() { } } class Program { static void Main(string[] args) { R2 r = new R2(); r.f<int>(); } }"; var compilation = CreateCompilation(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12); compilation.VerifyDiagnostics( // (6,14): error CS0306: The type 'int*' may not be used as a type argument // unsafe class R2 : R1<int*> Diagnostic(ErrorCode.ERR_BadTypeArgument, "R2").WithArguments("int*").WithLocation(6, 14)); compilation = CreateCompilation(source, parseOptions: TestOptions.Regular12); compilation.VerifyDiagnostics( // (6,14): error CS0227: Unsafe code may only appear if compiling with /unsafe // unsafe class R2 : R1<int*> Diagnostic(ErrorCode.ERR_IllegalUnsafe, "R2").WithLocation(6, 14), // (6,14): error CS0306: The type 'int*' may not be used as a type argument // unsafe class R2 : R1<int*> Diagnostic(ErrorCode.ERR_BadTypeArgument, "R2").WithArguments("int*").WithLocation(6, 14)); } [Fact] [WorkItem(41779, "https://github.com/dotnet/roslyn/issues/41779")] public void Bug41779_Original() { var source = @"interface I { object GetService(); } static class Program { static T GetService<T>(this I obj) => default; static void M(I provider) { provider.GetService<>(); provider.GetService<>().ToString(); provider.GetService<>(); } }"; CreateCompilation(source).VerifyDiagnostics( // (12,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(12, 9), // (13,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(13, 9), // (14,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(14, 9) ); } [Fact] [WorkItem(41779, "https://github.com/dotnet/roslyn/issues/41779")] public void Bug41779_DoubleTypeArg() { var source = @"interface I { object GetService(); } static class Program { static T1 GetService<T1, T2>(this I obj) => default; static void M(I provider) { provider.GetService<>(); provider.GetService<>().ToString(); provider.GetService<>(); } }"; CreateCompilation(source).VerifyDiagnostics( // (12,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(12, 9), // (12,18): error CS0308: The non-generic method 'I.GetService()' cannot be used with type arguments // provider.GetService<>(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetService<>").WithArguments("I.GetService()", "method").WithLocation(12, 18), // (13,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(13, 9), // (13,18): error CS0308: The non-generic method 'I.GetService()' cannot be used with type arguments // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetService<>").WithArguments("I.GetService()", "method").WithLocation(13, 18), // (14,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(14, 9), // (14,18): error CS0308: The non-generic method 'I.GetService()' cannot be used with type arguments // provider.GetService<>(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetService<>").WithArguments("I.GetService()", "method").WithLocation(14, 18) ); } [Fact] [WorkItem(41779, "https://github.com/dotnet/roslyn/issues/41779")] public void Bug41779_Instance() { var source = @"interface I { object GetService(); } interface J { object GetService<T>(); } interface K { object GetService<T1, T2>(); } static class Program { static void M(I provider) { provider.GetService<>(); provider.GetService<>().ToString(); } static void M(J provider) { provider.GetService<>(); provider.GetService<>().ToString(); } static void M(K provider) { provider.GetService<>(); provider.GetService<>().ToString(); } }"; CreateCompilation(source).VerifyDiagnostics( // (20,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(20, 9), // (20,18): error CS0308: The non-generic method 'I.GetService()' cannot be used with type arguments // provider.GetService<>(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetService<>").WithArguments("I.GetService()", "method").WithLocation(20, 18), // (21,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(21, 9), // (21,18): error CS0308: The non-generic method 'I.GetService()' cannot be used with type arguments // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetService<>").WithArguments("I.GetService()", "method").WithLocation(21, 18), // (26,9): error CS0305: Using the generic method group 'GetService' requires 1 type arguments // provider.GetService<>(); Diagnostic(ErrorCode.ERR_BadArity, "provider.GetService<>").WithArguments("GetService", "method group", "1").WithLocation(26, 9), // (27,9): error CS0305: Using the generic method group 'GetService' requires 1 type arguments // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_BadArity, "provider.GetService<>").WithArguments("GetService", "method group", "1").WithLocation(27, 9), // (32,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(32, 9), // (32,18): error CS0305: Using the generic method 'K.GetService<T1, T2>()' requires 2 type arguments // provider.GetService<>(); Diagnostic(ErrorCode.ERR_BadArity, "GetService<>").WithArguments("K.GetService<T1, T2>()", "method", "2").WithLocation(32, 18), // (33,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetService<>").WithLocation(33, 9), // (33,18): error CS0305: Using the generic method 'K.GetService<T1, T2>()' requires 2 type arguments // provider.GetService<>().ToString(); Diagnostic(ErrorCode.ERR_BadArity, "GetService<>").WithArguments("K.GetService<T1, T2>()", "method", "2").WithLocation(33, 18) ); } [Fact] [WorkItem(41779, "https://github.com/dotnet/roslyn/issues/41779")] public void Bug41779_Extension() { var source = @"interface I{} static class Program { static void GetServiceA(this I obj){} static T GetServiceB<T>(this I obj) => default; static T1 GetServiceC<T1, T2>(this I obj) => default; static void M(I provider) { provider.GetServiceA<>(); provider.GetServiceA<>().ToString(); provider.GetServiceB<>(); provider.GetServiceB<>().ToString(); provider.GetServiceC<>(); provider.GetServiceC<>().ToString(); } }"; CreateCompilation(source).VerifyDiagnostics( // (11,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetServiceA<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetServiceA<>").WithLocation(11, 9), // (11,18): error CS1061: 'I' does not contain a definition for 'GetServiceA' and no accessible extension method 'GetServiceA' accepting a first argument of type 'I' could be found (are you missing a using directive or an assembly reference?) // provider.GetServiceA<>(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "GetServiceA<>").WithArguments("I", "GetServiceA").WithLocation(11, 18), // (12,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetServiceA<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetServiceA<>").WithLocation(12, 9), // (12,18): error CS1061: 'I' does not contain a definition for 'GetServiceA' and no accessible extension method 'GetServiceA' accepting a first argument of type 'I' could be found (are you missing a using directive or an assembly reference?) // provider.GetServiceA<>().ToString(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "GetServiceA<>").WithArguments("I", "GetServiceA").WithLocation(12, 18), // (14,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetServiceB<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetServiceB<>").WithLocation(14, 9), // (15,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetServiceB<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetServiceB<>").WithLocation(15, 9), // (17,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetServiceC<>(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetServiceC<>").WithLocation(17, 9), // (17,18): error CS1061: 'I' does not contain a definition for 'GetServiceC' and no accessible extension method 'GetServiceC' accepting a first argument of type 'I' could be found (are you missing a using directive or an assembly reference?) // provider.GetServiceC<>(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "GetServiceC<>").WithArguments("I", "GetServiceC").WithLocation(17, 18), // (18,9): error CS8389: Omitting the type argument is not allowed in the current context // provider.GetServiceC<>().ToString(); Diagnostic(ErrorCode.ERR_OmittedTypeArgument, "provider.GetServiceC<>").WithLocation(18, 9), // (18,18): error CS1061: 'I' does not contain a definition for 'GetServiceC' and no accessible extension method 'GetServiceC' accepting a first argument of type 'I' could be found (are you missing a using directive or an assembly reference?) // provider.GetServiceC<>().ToString(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "GetServiceC<>").WithArguments("I", "GetServiceC").WithLocation(18, 18) ); } [Fact] [WorkItem(41779, "https://github.com/dotnet/roslyn/issues/41779")] public void Bug41779_Static() { var source = @"static class Program { static object GetServiceA(){ return null; } static T GetServiceB<T>() => default; static T1 GetServiceC<T1, T2>() => default; static void M() { GetServiceA<>(); GetServiceA<>().ToString(); GetServiceB<>(); GetServiceB<>().ToString(); GetServiceC<>(); GetServiceC<>().ToString(); } }"; CreateCompilation(source).VerifyDiagnostics( // (9,9): error CS0308: The non-generic method 'Program.GetServiceA()' cannot be used with type arguments // GetServiceA<>(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetServiceA<>").WithArguments("Program.GetServiceA()", "method").WithLocation(9, 9), // (10,9): error CS0308: The non-generic method 'Program.GetServiceA()' cannot be used with type arguments // GetServiceA<>().ToString(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "GetServiceA<>").WithArguments("Program.GetServiceA()", "method").WithLocation(10, 9), // (11,9): error CS0305: Using the generic method group 'GetServiceB' requires 1 type arguments // GetServiceB<>(); Diagnostic(ErrorCode.ERR_BadArity, "GetServiceB<>").WithArguments("GetServiceB", "method group", "1").WithLocation(11, 9), // (12,9): error CS0305: Using the generic method group 'GetServiceB' requires 1 type arguments // GetServiceB<>().ToString(); Diagnostic(ErrorCode.ERR_BadArity, "GetServiceB<>").WithArguments("GetServiceB", "method group", "1").WithLocation(12, 9), // (13,9): error CS0305: Using the generic method 'Program.GetServiceC<T1, T2>()' requires 2 type arguments // GetServiceC<>(); Diagnostic(ErrorCode.ERR_BadArity, "GetServiceC<>").WithArguments("Program.GetServiceC<T1, T2>()", "method", "2").WithLocation(13, 9), // (14,9): error CS0305: Using the generic method 'Program.GetServiceC<T1, T2>()' requires 2 type arguments // GetServiceC<>().ToString(); Diagnostic(ErrorCode.ERR_BadArity, "GetServiceC<>").WithArguments("Program.GetServiceC<T1, T2>()", "method", "2").WithLocation(14, 9) ); } [Fact, WorkItem(1279758, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1279758/")] public void RecursiveConstraintsFromUnifiedAssemblies_1() { var code = @" public abstract class A<T1, T2> where T1 : A<T1, T2> where T2 : A<T1, T2>.B<T1, T2> { public abstract class B<T3, T4> where T3 : A<T3, T4> where T4 : A<T3, T4>.B<T3, T4> { } } public class C : A<C, C.D> { public class D : A<C, C.D>.B<C, D> { } } "; var metadataComp = CreateEmptyCompilation(code, new[] { MscorlibRef_v20 }, assemblyName: "assembly1"); metadataComp.VerifyDiagnostics(); var comp = CreateCompilation(@"System.Console.WriteLine(typeof(C.D).FullName);", new[] { metadataComp.EmitToImageReference() }, targetFramework: TargetFramework.Mscorlib461); // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy DiagnosticDescription expectedDiagnostic = Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1); // These are unification use-site diagnostics. The original stackoverflow bug here came from checking constraints as part of // unification diagnostic calculation, so we want to verify that these are present to make sure we're testing the correct scenario. comp.VerifyDiagnostics( expectedDiagnostic, // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy expectedDiagnostic ); CompileAndVerify( comp.WithOptions(comp.Options.WithSpecificDiagnosticOptions("CS1701", ReportDiagnostic.Suppress)), expectedOutput: "C+D"); var c = comp.GetTypeByMetadataName("C"); Assert.True(c.ContainingModule.HasUnifiedReferences); Assert.Equal(expectedDiagnostic.Code, c.GetUseSiteDiagnostic().Code); } [Fact, WorkItem(1279758, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1279758/")] public void RecursiveConstraintsFromUnifiedAssemblies_2() { var remappedCode = @"public class F {}"; var remappedComp11 = CreateCompilation( new AssemblyIdentity("remapped", new Version("1.0.0.0"), publicKeyOrToken: SigningTestHelpers.PublicKey, hasPublicKey: true), new[] { remappedCode }, TargetFrameworkUtil.NetStandard20References.ToArray(), TestOptions.ReleaseDll.WithPublicSign(true)); var remappedComp12 = CreateCompilation( new AssemblyIdentity("remapped", new Version("2.0.0.0"), publicKeyOrToken: SigningTestHelpers.PublicKey, hasPublicKey: true), new[] { remappedCode }, TargetFrameworkUtil.NetStandard20References.ToArray(), TestOptions.ReleaseDll.WithPublicSign(true)); var code = @" public abstract class A<T1, T2> where T1 : A<T1, T2> where T2 : A<T1, T2>.B<T1, T2> { public abstract class B<T3, T4> where T3 : A<T3, T4> where T4 : A<T3, T4>.B<T3, T4> { } } public class C : A<C, C.D> { public class D : A<C, C.D>.B<C, D> { } } public class G : F {} "; var metadataComp = CreateCompilation(code, new[] { remappedComp11.EmitToImageReference() }, assemblyName: "intermediate", targetFramework: TargetFramework.NetStandard20); metadataComp.VerifyDiagnostics(); var comp = CreateCompilation(@" System.Console.WriteLine(typeof(C.D).FullName); System.Console.WriteLine(typeof(G).FullName); ", new[] { metadataComp.EmitToImageReference(), remappedComp12.EmitToImageReference() }, targetFramework: TargetFramework.NetStandard20); comp.VerifyDiagnostics( // warning CS1701: Assuming assembly reference 'remapped, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' used by 'intermediate' matches identity 'remapped, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' of 'remapped', you may need to supply runtime policy Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("remapped, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "intermediate", "remapped, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "remapped").WithLocation(1, 1) ); var c = comp.GetTypeByMetadataName("C"); Assert.Null(c.GetUseSiteDiagnostic()); Assert.True(c.ContainingModule.HasUnifiedReferences); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68223")] public void ConstraintCycle_NestedTypeFromBase_01() { var src = """ #nullable enable interface ISetup<T> { T Data { get; set; } } interface Base { public abstract class Nest { } } interface Base<N> : Base, ISetup<N> where N : Base<N>.Nest { } """; var comp = CreateCompilation(src); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var nest = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(i => i.Identifier.ValueText == "Nest").Single(); Assert.Null(model.GetAliasInfo(nest)); Assert.Equal("Base.Nest", model.GetTypeInfo(nest).Type.ToDisplayString()); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68223")] public void ConstraintCycle_NestedTypeFromBase_02() { var src = """ #nullable enable interface ISetup<T> where T : new() { T Data { get; set; } } interface Base { public abstract class Nest { } } interface Base<N> : Base, ISetup<N> where N : Base<N>.Nest { } """; var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (5,11): error CS0310: 'N' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ISetup<T>' // interface Base<N> : Base, ISetup<N> where N : Base<N>.Nest { } Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "Base").WithArguments("ISetup<T>", "T", "N").WithLocation(5, 11) ); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var nest = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(i => i.Identifier.ValueText == "Nest").Single(); Assert.Null(model.GetAliasInfo(nest)); Assert.Equal("Base.Nest", model.GetTypeInfo(nest).Type.ToDisplayString()); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41733")] public void TypeParameter_BaseType_ReturnsNull() { var source = """ abstract class Base { public abstract void Method(); } class Derived<T> where T : Base { } """; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); var typeParameter = (ITypeParameterSymbol)comp.GetTypeByMetadataName("Derived`1").TypeParameters[0].GetPublicSymbol(); Assert.Null(typeParameter.BaseType); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41733")] public void MethodTypeParameter_BaseType_ReturnsNull() { var source = """ class C { void M<T>() where T : class { } } """; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); var typeParameter = (ITypeParameterSymbol)comp.GetTypeByMetadataName("C").GetMethod("M").TypeParameters[0].GetPublicSymbol(); Assert.Null(typeParameter.BaseType); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41733")] public void ObjectType_BaseType_ReturnsNull() { var comp = CreateCompilation(""); comp.VerifyDiagnostics(); var objectType = (INamedTypeSymbol)comp.GetSpecialType(SpecialType.System_Object).GetPublicSymbol(); Assert.Null(objectType.BaseType); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41733")] public void InterfaceType_BaseType_ReturnsNull() { var source = """ interface IMyInterface { void Method(); } """; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); var interfaceType = (INamedTypeSymbol)comp.GetTypeByMetadataName("IMyInterface").GetPublicSymbol(); Assert.Null(interfaceType.BaseType); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41733")] public void PointerType_BaseType_ReturnsNull() { var source = """ unsafe class C { int* ptr; } """; var comp = CreateCompilation(source, options: TestOptions.UnsafeDebugDll); comp.VerifyDiagnostics( // (3,10): warning CS0169: The field 'C.ptr' is never used // int* ptr; Diagnostic(ErrorCode.WRN_UnreferencedField, "ptr").WithArguments("C.ptr").WithLocation(3, 10)); var pointerType = (IPointerTypeSymbol)comp.GetTypeByMetadataName("C").GetField("ptr").Type.GetPublicSymbol(); Assert.Null(pointerType.BaseType); } } }