protected BinderFactory(LanguageCompilation compilation, SyntaxTree syntaxTree) { _compilation = compilation; _syntaxTree = syntaxTree; _binderFactoryVisitorPool = new ObjectPool <BinderFactoryVisitor>(() => Language.CompilationFactory.CreateBinderFactoryVisitor(this), 64); _buckStopsHereBinder = new BuckStopsHereBinder(compilation); }
private static Binder CreateBinderChain( CSharpCompilation compilation, PEModuleSymbol module, NamespaceSymbol @namespace, ImmutableArray<ImmutableArray<ImportRecord>> importRecordGroups) { var stack = ArrayBuilder<string>.GetInstance(); while ((object)@namespace != null) { stack.Push(@namespace.Name); @namespace = @namespace.ContainingNamespace; } Binder binder = new BuckStopsHereBinder(compilation); var hasImports = !importRecordGroups.IsDefaultOrEmpty; var numImportStringGroups = hasImports ? importRecordGroups.Length : 0; var currentStringGroup = numImportStringGroups - 1; // PERF: We used to call compilation.GetCompilationNamespace on every iteration, // but that involved walking up to the global namespace, which we have to do // anyway. Instead, we'll inline the functionality into our own walk of the // namespace chain. @namespace = compilation.GlobalNamespace; while (stack.Count > 0) { var namespaceName = stack.Pop(); if (namespaceName.Length > 0) { // We're re-getting the namespace, rather than using the one containing // the current frame method, because we want the merged namespace. @namespace = @namespace.GetNestedNamespace(namespaceName); Debug.Assert((object)@namespace != null, $"We worked backwards from symbols to names, but no symbol exists for name '{namespaceName}'"); } else { Debug.Assert((object)@namespace == (object)compilation.GlobalNamespace); } Imports imports = null; if (hasImports) { if (currentStringGroup < 0) { Debug.WriteLine($"No import string group for namespace '{@namespace}'"); break; } var importsBinder = new InContainerBinder(@namespace, binder); imports = BuildImports(compilation, module, importRecordGroups[currentStringGroup], importsBinder); currentStringGroup--; } binder = new InContainerBinder(@namespace, binder, imports); } stack.Free(); if (currentStringGroup >= 0) { // CONSIDER: We could lump these into the outermost namespace. It's probably not worthwhile since // the usings are already for the wrong method. Debug.WriteLine($"Found {currentStringGroup + 1} import string groups without corresponding namespaces"); } return binder; }
public void TestConversionsWithCustomModifiers() { var text = @" class C { int[] a; } "; var ilAssemblyReference = TestReferences.SymbolsTests.CustomModifiers.Modifiers.dll; var compilation = CreateCompilationWithMscorlib(text, new MetadataReference[] { ilAssemblyReference }); compilation.VerifyDiagnostics( // (4,11): warning CS0169: The field 'C.a' is never used // int[] a; Diagnostic(ErrorCode.WRN_UnreferencedField, "a").WithArguments("C.a") ); var classC = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var typeIntArray = classC.GetMember<FieldSymbol>("a").Type; var interfaceI3 = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("I3"); var typeIntArrayWithCustomModifiers = interfaceI3.GetMember<MethodSymbol>("M1").Parameters.Single().Type; Assert.True(typeIntArrayWithCustomModifiers.HasCustomModifiers(flagNonDefaultArraySizesOrLowerBounds:false)); var conv = new BuckStopsHereBinder(compilation).Conversions; HashSet<DiagnosticInfo> useSiteDiagnostics = null; // no custom modifiers to custom modifiers Assert.Equal(ConversionKind.Identity, conv.ClassifyConversion(typeIntArray, typeIntArrayWithCustomModifiers, ref useSiteDiagnostics).Kind); // custom modifiers to no custom modifiers Assert.Equal(ConversionKind.Identity, conv.ClassifyConversion(typeIntArrayWithCustomModifiers, typeIntArray, ref useSiteDiagnostics).Kind); // custom modifiers to custom modifiers Assert.Equal(ConversionKind.Identity, conv.ClassifyConversion(typeIntArrayWithCustomModifiers, typeIntArrayWithCustomModifiers, ref useSiteDiagnostics).Kind); }
public void Test1() { var mscorlibRef = TestReferences.NetFx.v4_0_21006.mscorlib; var compilation = CSharpCompilation.Create("Test", references: new MetadataReference[] { mscorlibRef }); var sys = compilation.GlobalNamespace.ChildNamespace("System"); Conversions c = new BuckStopsHereBinder(compilation).Conversions; var types = new TypeSymbol[] { sys.ChildType("Object"), sys.ChildType("String"), sys.ChildType("Array"), sys.ChildType("Int64"), sys.ChildType("UInt64"), sys.ChildType("Int32"), sys.ChildType("UInt32"), sys.ChildType("Int16"), sys.ChildType("UInt16"), sys.ChildType("SByte"), sys.ChildType("Byte"), sys.ChildType("Double"), sys.ChildType("Single"), sys.ChildType("Decimal"), sys.ChildType("Char"), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Int64")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("UInt64")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Int32")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("UInt32")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Int16")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("UInt16")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("SByte")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Byte")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Double")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Single")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Decimal")), sys.ChildType("Nullable", 1).Construct(sys.ChildType("Char")), sys.ChildType("Exception"), sys.ChildNamespace("Collections").ChildType("IEnumerable"), sys.ChildNamespace("Collections").ChildNamespace("Generic").ChildType("IEnumerable", 1).Construct(sys.ChildType("Object")), sys.ChildNamespace("Collections").ChildNamespace("Generic").ChildType("IEnumerable", 1).Construct(sys.ChildType("String")), sys.ChildNamespace("Collections").ChildNamespace("Generic").ChildType("IEnumerable", 1).Construct(sys.ChildType("Char")), compilation.CreateArrayTypeSymbol(sys.ChildType("String")), compilation.CreateArrayTypeSymbol(sys.ChildType("Object")), sys.ChildNamespace("Collections").ChildNamespace("Generic").ChildType("IList", 1).Construct(sys.ChildType("String")), sys.ChildNamespace("Collections").ChildNamespace("Generic").ChildType("IList", 1).Construct(sys.ChildType("Object")), sys.ChildType("ArgumentException"), sys.ChildType("Delegate"), sys.ChildType("Func", 2).Construct(sys.ChildType("Exception"), sys.ChildType("Exception")), sys.ChildType("Func", 2).Construct(sys.ChildType("ArgumentException"), sys.ChildType("Object")), sys.ChildNamespace("Runtime").ChildNamespace("Serialization").ChildType("ISerializable"), sys.ChildType("IComparable", 0), }; const ConversionKind Non = ConversionKind.NoConversion; const ConversionKind Idn = ConversionKind.Identity; const ConversionKind Inm = ConversionKind.ImplicitNumeric; const ConversionKind Inl = ConversionKind.ImplicitNullable; const ConversionKind Irf = ConversionKind.ImplicitReference; const ConversionKind Box = ConversionKind.Boxing; const ConversionKind Xrf = ConversionKind.ExplicitReference; const ConversionKind Ubx = ConversionKind.Unboxing; const ConversionKind Xnl = ConversionKind.ExplicitNullable; const ConversionKind Xnm = ConversionKind.ExplicitNumeric; ConversionKind[,] conversions = { // from obj str arr i64 u64 i32 u32 i16 u16 i08 u08 r64 r32 dec chr ni64 nu64 ni32 nu32 ni16 nu16 ni8 nu8 nr64 nr32 ndc nch exc ien ieo ies iec ars aro ils ilo aex del fee fao ser cmp // to: /*obj*/ { Idn, Irf, Irf, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Irf }, /*str*/ { Xrf, Idn, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Non, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf }, /*arr*/ { Xrf, Non, Idn, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Xrf, Irf, Irf, Xrf, Xrf, Non, Non, Non, Non, Xrf, Xrf }, /*i64*/ { Ubx, Non, Non, Idn, Xnm, Inm, Inm, Inm, Inm, Inm, Inm, Xnm, Xnm, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*u64*/ { Ubx, Non, Non, Xnm, Idn, Xnm, Inm, Xnm, Inm, Xnm, Inm, Xnm, Xnm, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*i32*/ { Ubx, Non, Non, Xnm, Xnm, Idn, Xnm, Inm, Inm, Inm, Inm, Xnm, Xnm, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*u32*/ { Ubx, Non, Non, Xnm, Xnm, Xnm, Idn, Xnm, Inm, Xnm, Inm, Xnm, Xnm, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*i16*/ { Ubx, Non, Non, Xnm, Xnm, Xnm, Xnm, Idn, Xnm, Inm, Inm, Xnm, Xnm, Xnm, Xnm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*u16*/ { Ubx, Non, Non, Xnm, Xnm, Xnm, Xnm, Xnm, Idn, Xnm, Inm, Xnm, Xnm, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*i08*/ { Ubx, Non, Non, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Idn, Xnm, Xnm, Xnm, Xnm, Xnm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*u08*/ { Ubx, Non, Non, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Idn, Xnm, Xnm, Xnm, Xnm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*r64*/ { Ubx, Non, Non, Inm, Inm, Inm, Inm, Inm, Inm, Inm, Inm, Idn, Inm, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*r32*/ { Ubx, Non, Non, Inm, Inm, Inm, Inm, Inm, Inm, Inm, Inm, Xnm, Idn, Xnm, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*dec*/ { Ubx, Non, Non, Inm, Inm, Inm, Inm, Inm, Inm, Inm, Inm, Xnm, Xnm, Idn, Inm, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*chr*/ { Ubx, Non, Non, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Xnm, Idn, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*ni64*/ { Ubx, Non, Non, Inl, Xnl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Xnl, Xnl, Inl, Idn, Xnl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Xnl, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nu64*/ { Ubx, Non, Non, Xnl, Inl, Xnl, Inl, Xnl, Inl, Xnl, Inl, Xnl, Xnl, Xnl, Inl, Xnl, Idn, Xnl, Inl, Xnl, Inl, Xnl, Inl, Xnl, Xnl, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*ni32*/ { Ubx, Non, Non, Xnl, Xnl, Inl, Xnl, Inl, Inl, Inl, Inl, Xnl, Xnl, Xnl, Inl, Xnl, Xnl, Idn, Xnl, Inl, Inl, Inl, Inl, Xnl, Xnl, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nu32*/ { Ubx, Non, Non, Xnl, Xnl, Xnl, Inl, Xnl, Inl, Xnl, Inl, Xnl, Xnl, Xnl, Inl, Xnl, Xnl, Xnl, Idn, Xnl, Inl, Xnl, Inl, Xnl, Xnl, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*ni16*/ { Ubx, Non, Non, Xnl, Xnl, Xnl, Xnl, Inl, Xnl, Inl, Inl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Idn, Xnl, Inl, Inl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nu16*/ { Ubx, Non, Non, Xnl, Xnl, Xnl, Xnl, Xnl, Inl, Xnl, Inl, Xnl, Xnl, Xnl, Inl, Xnl, Xnl, Xnl, Xnl, Xnl, Idn, Xnl, Inl, Xnl, Xnl, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*ni8*/ { Ubx, Non, Non, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Inl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Idn, Xnl, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nu8*/ { Ubx, Non, Non, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Inl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Idn, Xnl, Xnl, Xnl, Xnl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nr64*/ { Ubx, Non, Non, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Idn, Inl, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nr32*/ { Ubx, Non, Non, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Inl, Xnl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Idn, Xnl, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*ndc*/ { Ubx, Non, Non, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Xnl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Inl, Xnl, Xnl, Idn, Inl, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*nch*/ { Ubx, Non, Non, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Inl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Xnl, Idn, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Ubx }, /*exc*/ { Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Idn, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf, Irf, Non, Non, Non, Xrf, Xrf }, /*ien*/ { Xrf, Irf, Irf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Idn, Irf, Irf, Irf, Irf, Irf, Irf, Irf, Xrf, Xrf, Non, Non, Xrf, Xrf }, /*ieo*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Idn, Irf, Xrf, Irf, Irf, Irf, Irf, Xrf, Xrf, Non, Non, Xrf, Xrf }, /*ies*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Idn, Xrf, Irf, Xrf, Irf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf }, /*iec*/ { Xrf, Irf, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Xrf, Idn, Non, Non, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf }, /*ars*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Non, Idn, Xrf, Xrf, Xrf, Non, Non, Non, Non, Non, Non }, /*aro*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Non, Irf, Idn, Xrf, Xrf, Non, Non, Non, Non, Non, Non }, /*ils*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Xrf, Xrf, Irf, Xrf, Idn, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf }, /*ilo*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Xrf, Xrf, Irf, Irf, Xrf, Idn, Xrf, Xrf, Non, Non, Xrf, Xrf }, /*aex*/ { Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf, Idn, Non, Non, Non, Xrf, Xrf }, /*del*/ { Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf, Non, Idn, Irf, Irf, Xrf, Xrf }, /*fee*/ { Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Idn, Xrf, Xrf, Non }, /*fao*/ { Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Xrf, Irf, Idn, Xrf, Non }, /*ser*/ { Xrf, Non, Xrf, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Irf, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf, Irf, Irf, Irf, Irf, Idn, Xrf }, /*cmp*/ { Xrf, Irf, Xrf, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Box, Xrf, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Xrf, Xrf, Xrf, Non, Non, Xrf, Idn }, }; HashSet<DiagnosticInfo> useSiteDiagnostics = null; for (int i = 0; i < types.Length; ++i) { for (int j = 0; j < types.Length; ++j) { var kind = conversions[i, j]; var result = c.ClassifyConversion(types[j], types[i], ref useSiteDiagnostics); //Assert.Equal doesn't allow a string explanation, so provide one this way. if (kind != result.Kind) { var result2 = c.ClassifyConversion(types[j], types[i], ref useSiteDiagnostics); // set breakpoint here if this test is failing... Assert.True(false, string.Format("Expected {0} but got {1} when converting {2} -> {3}", kind, result, types[j], types[i])); } } } // UNDONE: Not tested yet: // UNDONE: Type parameter reference, boxing and unboxing conversions // UNDONE: User-defined conversions // UNDONE: Dynamic conversions // UNDONE: Enum conversions // UNDONE: Conversions involving expressions: null, lambda, method group }