// 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.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Test.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using ReferenceEqualityComparer = Roslyn.Utilities.ReferenceEqualityComparer;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
public class NativeIntegerTests : CSharpTestBase
{
[Fact]
public void LanguageVersion()
{
var source =
@"interface I
{
nint Add(nint x, nuint y);
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(
// (3,5): error CS8400: Feature 'native-sized integers' is not available in C# 8.0. Please use language version 9.0 or greater.
// nint Add(nint x, nuint y);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "nint").WithArguments("native-sized integers", "9.0").WithLocation(3, 5),
// (3,14): error CS8400: Feature 'native-sized integers' is not available in C# 8.0. Please use language version 9.0 or greater.
// nint Add(nint x, nuint y);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "nint").WithArguments("native-sized integers", "9.0").WithLocation(3, 14),
// (3,22): error CS8400: Feature 'native-sized integers' is not available in C# 8.0. Please use language version 9.0 or greater.
// nint Add(nint x, nuint y);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "nuint").WithArguments("native-sized integers", "9.0").WithLocation(3, 22));
comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
}
///
/// System.IntPtr and System.UIntPtr definitions from metadata.
///
[Fact]
public void TypeDefinitions_FromMetadata()
{
var source =
@"interface I
{
void F1(System.IntPtr x, nint y);
void F2(System.UIntPtr x, nuint y);
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
var type = comp.GetTypeByMetadataName("System.IntPtr");
VerifyType(type, signed: true, isNativeInt: false);
VerifyType(type.GetPublicSymbol(), signed: true, isNativeInt: false);
type = comp.GetTypeByMetadataName("System.UIntPtr");
VerifyType(type, signed: false, isNativeInt: false);
VerifyType(type.GetPublicSymbol(), signed: false, isNativeInt: false);
var method = comp.GetMember("I.F1");
Assert.Equal("void I.F1(System.IntPtr x, nint y)", method.ToTestDisplayString());
Assert.Equal("Sub I.F1(x As System.IntPtr, y As System.IntPtr)", VisualBasic.SymbolDisplay.ToDisplayString(method.GetPublicSymbol(), SymbolDisplayFormat.TestFormat));
VerifyTypes((NamedTypeSymbol)method.Parameters[0].Type, (NamedTypeSymbol)method.Parameters[1].Type, signed: true);
method = comp.GetMember("I.F2");
Assert.Equal("void I.F2(System.UIntPtr x, nuint y)", method.ToTestDisplayString());
Assert.Equal("Sub I.F2(x As System.UIntPtr, y As System.UIntPtr)", VisualBasic.SymbolDisplay.ToDisplayString(method.GetPublicSymbol(), SymbolDisplayFormat.TestFormat));
VerifyTypes((NamedTypeSymbol)method.Parameters[0].Type, (NamedTypeSymbol)method.Parameters[1].Type, signed: false);
}
///
/// System.IntPtr and System.UIntPtr definitions from source.
///
[Fact]
public void TypeDefinitions_FromSource()
{
var sourceA =
@"namespace System
{
public class Object
{
public virtual string ToString() => null;
public virtual int GetHashCode() => 0;
public virtual bool Equals(object obj) => false;
}
public class String { }
public abstract class ValueType
{
public override string ToString() => null;
public override int GetHashCode() => 0;
public override bool Equals(object obj) => false;
}
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public interface IEquatable
{
bool Equals(T other);
}
public struct IntPtr : IEquatable
{
public override string ToString() => null;
public override int GetHashCode() => 0;
public override bool Equals(object obj) => false;
bool IEquatable.Equals(IntPtr other) => false;
}
public struct UIntPtr : IEquatable
{
public override string ToString() => null;
public override int GetHashCode() => 0;
public override bool Equals(object obj) => false;
bool IEquatable.Equals(UIntPtr other) => false;
}
}";
var sourceB =
@"interface I
{
void F1(System.IntPtr x, nint y);
void F2(System.UIntPtr x, nuint y);
}";
var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
verify(comp);
comp = CreateEmptyCompilation(sourceA);
comp.VerifyDiagnostics();
var ref1 = comp.ToMetadataReference();
var ref2 = comp.EmitToImageReference();
comp = CreateEmptyCompilation(sourceB, references: new[] { ref1 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
verify(comp);
comp = CreateEmptyCompilation(sourceB, references: new[] { ref2 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
verify(comp);
static void verify(CSharpCompilation comp)
{
var type = comp.GetTypeByMetadataName("System.IntPtr");
VerifyType(type, signed: true, isNativeInt: false);
VerifyType(type.GetPublicSymbol(), signed: true, isNativeInt: false);
type = comp.GetTypeByMetadataName("System.UIntPtr");
VerifyType(type, signed: false, isNativeInt: false);
VerifyType(type.GetPublicSymbol(), signed: false, isNativeInt: false);
var method = comp.GetMember("I.F1");
Assert.Equal("void I.F1(System.IntPtr x, nint y)", method.ToTestDisplayString());
VerifyTypes((NamedTypeSymbol)method.Parameters[0].Type, (NamedTypeSymbol)method.Parameters[1].Type, signed: true);
method = comp.GetMember("I.F2");
Assert.Equal("void I.F2(System.UIntPtr x, nuint y)", method.ToTestDisplayString());
VerifyTypes((NamedTypeSymbol)method.Parameters[0].Type, (NamedTypeSymbol)method.Parameters[1].Type, signed: false);
}
}
private static void VerifyType(NamedTypeSymbol type, bool signed, bool isNativeInt)
{
Assert.Equal(signed ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr, type.SpecialType);
Assert.Equal(SymbolKind.NamedType, type.Kind);
Assert.Equal(TypeKind.Struct, type.TypeKind);
Assert.Same(type, type.ConstructedFrom);
Assert.Equal(isNativeInt, type.IsNativeIntegerType);
Assert.Equal(signed ? "IntPtr" : "UIntPtr", type.Name);
if (isNativeInt)
{
VerifyMembers(type);
}
}
private static void VerifyType(INamedTypeSymbol type, bool signed, bool isNativeInt)
{
Assert.Equal(signed ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr, type.SpecialType);
Assert.Equal(SymbolKind.NamedType, type.Kind);
Assert.Equal(TypeKind.Struct, type.TypeKind);
Assert.Same(type, type.ConstructedFrom);
Assert.Equal(isNativeInt, type.IsNativeIntegerType);
Assert.Equal(signed ? "IntPtr" : "UIntPtr", type.Name);
if (isNativeInt)
{
VerifyMembers(type);
}
}
private static void VerifyTypes(INamedTypeSymbol underlyingType, INamedTypeSymbol nativeIntegerType, bool signed)
{
VerifyType(underlyingType, signed, isNativeInt: false);
VerifyType(nativeIntegerType, signed, isNativeInt: true);
Assert.Same(underlyingType.ContainingSymbol, nativeIntegerType.ContainingSymbol);
Assert.Same(underlyingType.Name, nativeIntegerType.Name);
VerifyMembers(underlyingType, nativeIntegerType, signed);
VerifyInterfaces(underlyingType, underlyingType.Interfaces, nativeIntegerType, nativeIntegerType.Interfaces);
Assert.NotSame(underlyingType, nativeIntegerType);
Assert.Same(underlyingType, nativeIntegerType.NativeIntegerUnderlyingType);
Assert.NotEqual(underlyingType, nativeIntegerType);
Assert.NotEqual(nativeIntegerType, underlyingType);
Assert.False(underlyingType.Equals(nativeIntegerType));
Assert.False(((IEquatable)underlyingType).Equals(nativeIntegerType));
Assert.False(underlyingType.Equals(nativeIntegerType, SymbolEqualityComparer.Default));
Assert.False(underlyingType.Equals(nativeIntegerType, SymbolEqualityComparer.IncludeNullability));
Assert.False(underlyingType.Equals(nativeIntegerType, SymbolEqualityComparer.ConsiderEverything));
Assert.True(underlyingType.Equals(nativeIntegerType, TypeCompareKind.IgnoreNativeIntegers));
Assert.Equal(underlyingType.GetHashCode(), nativeIntegerType.GetHashCode());
}
private static void VerifyInterfaces(INamedTypeSymbol underlyingType, ImmutableArray underlyingInterfaces, INamedTypeSymbol nativeIntegerType, ImmutableArray nativeIntegerInterfaces)
{
Assert.Equal(underlyingInterfaces.Length, nativeIntegerInterfaces.Length);
for (int i = 0; i < underlyingInterfaces.Length; i++)
{
verifyInterface(underlyingInterfaces[i], nativeIntegerInterfaces[i]);
}
void verifyInterface(INamedTypeSymbol underlyingInterface, INamedTypeSymbol nativeIntegerInterface)
{
Assert.True(underlyingInterface.Equals(nativeIntegerInterface, TypeCompareKind.IgnoreNativeIntegers));
for (int i = 0; i < underlyingInterface.TypeArguments.Length; i++)
{
var underlyingTypeArgument = underlyingInterface.TypeArguments[i];
var nativeIntegerTypeArgument = nativeIntegerInterface.TypeArguments[i];
Assert.Equal(underlyingTypeArgument.Equals(underlyingType, TypeCompareKind.AllIgnoreOptions), nativeIntegerTypeArgument.Equals(nativeIntegerType, TypeCompareKind.AllIgnoreOptions));
}
}
}
private static void VerifyMembers(INamedTypeSymbol underlyingType, INamedTypeSymbol nativeIntegerType, bool signed)
{
Assert.Empty(nativeIntegerType.GetTypeMembers());
var nativeIntegerMembers = nativeIntegerType.GetMembers();
var underlyingMembers = underlyingType.GetMembers();
var nativeIntegerMemberNames = nativeIntegerType.MemberNames;
AssertEx.Equal(nativeIntegerMembers.SelectAsArray(m => m.Name), nativeIntegerMemberNames);
var expectedMembers = underlyingMembers.WhereAsArray(m => includeUnderlyingMember(m)).Sort(SymbolComparison).SelectAsArray(m => m.ToTestDisplayString());
var actualMembers = nativeIntegerMembers.WhereAsArray(m => includeNativeIntegerMember(m)).Sort(SymbolComparison).SelectAsArray(m => m.ToTestDisplayString().Replace(signed ? "nint" : "nuint", signed ? "System.IntPtr" : "System.UIntPtr"));
AssertEx.Equal(expectedMembers, actualMembers);
static bool includeUnderlyingMember(ISymbol underlyingMember)
{
if (underlyingMember.DeclaredAccessibility != Accessibility.Public)
{
return false;
}
switch (underlyingMember.Kind)
{
case SymbolKind.Method:
var method = (IMethodSymbol)underlyingMember;
if (method.IsGenericMethod)
{
return false;
}
switch (method.MethodKind)
{
case MethodKind.Ordinary:
return !IsSkippedMethodName(method.Name);
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
return includeUnderlyingMember(method.AssociatedSymbol);
default:
return false;
}
case SymbolKind.Property:
var property = (IPropertySymbol)underlyingMember;
return property.Parameters.Length == 0 && !IsSkippedPropertyName(property.Name);
default:
return false;
}
}
static bool includeNativeIntegerMember(ISymbol nativeIntegerMember)
{
return !(nativeIntegerMember is IMethodSymbol { MethodKind: MethodKind.Constructor });
}
}
private static void VerifyTypes(NamedTypeSymbol underlyingType, NamedTypeSymbol nativeIntegerType, bool signed)
{
VerifyType(underlyingType, signed, isNativeInt: false);
VerifyType(nativeIntegerType, signed, isNativeInt: true);
Assert.Same(underlyingType.ContainingSymbol, nativeIntegerType.ContainingSymbol);
Assert.Same(underlyingType.Name, nativeIntegerType.Name);
VerifyMembers(underlyingType, nativeIntegerType, signed);
VerifyInterfaces(underlyingType, underlyingType.InterfacesNoUseSiteDiagnostics(), nativeIntegerType, nativeIntegerType.InterfacesNoUseSiteDiagnostics());
VerifyInterfaces(underlyingType, underlyingType.GetDeclaredInterfaces(null), nativeIntegerType, nativeIntegerType.GetDeclaredInterfaces(null));
Assert.Null(underlyingType.NativeIntegerUnderlyingType);
Assert.Same(nativeIntegerType, underlyingType.AsNativeInteger());
Assert.Same(underlyingType, nativeIntegerType.NativeIntegerUnderlyingType);
VerifyEqualButDistinct(underlyingType, underlyingType.AsNativeInteger());
VerifyEqualButDistinct(nativeIntegerType, nativeIntegerType.NativeIntegerUnderlyingType);
VerifyEqualButDistinct(underlyingType, nativeIntegerType);
VerifyTypes(underlyingType.GetPublicSymbol(), nativeIntegerType.GetPublicSymbol(), signed);
}
private static void VerifyEqualButDistinct(NamedTypeSymbol underlyingType, NamedTypeSymbol nativeIntegerType)
{
Assert.NotSame(underlyingType, nativeIntegerType);
Assert.NotEqual(underlyingType, nativeIntegerType);
Assert.NotEqual(nativeIntegerType, underlyingType);
Assert.False(underlyingType.Equals(nativeIntegerType, TypeCompareKind.ConsiderEverything));
Assert.False(nativeIntegerType.Equals(underlyingType, TypeCompareKind.ConsiderEverything));
Assert.True(underlyingType.Equals(nativeIntegerType, TypeCompareKind.IgnoreNativeIntegers));
Assert.True(nativeIntegerType.Equals(underlyingType, TypeCompareKind.IgnoreNativeIntegers));
Assert.Equal(underlyingType.GetHashCode(), nativeIntegerType.GetHashCode());
}
private static void VerifyInterfaces(NamedTypeSymbol underlyingType, ImmutableArray underlyingInterfaces, NamedTypeSymbol nativeIntegerType, ImmutableArray nativeIntegerInterfaces)
{
Assert.Equal(underlyingInterfaces.Length, nativeIntegerInterfaces.Length);
for (int i = 0; i < underlyingInterfaces.Length; i++)
{
verifyInterface(underlyingInterfaces[i], nativeIntegerInterfaces[i]);
}
void verifyInterface(NamedTypeSymbol underlyingInterface, NamedTypeSymbol nativeIntegerInterface)
{
Assert.True(underlyingInterface.Equals(nativeIntegerInterface, TypeCompareKind.IgnoreNativeIntegers));
for (int i = 0; i < underlyingInterface.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Length; i++)
{
var underlyingTypeArgument = underlyingInterface.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[i].Type;
var nativeIntegerTypeArgument = nativeIntegerInterface.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[i].Type;
Assert.Equal(underlyingTypeArgument.Equals(underlyingType, TypeCompareKind.AllIgnoreOptions), nativeIntegerTypeArgument.Equals(nativeIntegerType, TypeCompareKind.AllIgnoreOptions));
}
}
}
private static void VerifyMembers(NamedTypeSymbol underlyingType, NamedTypeSymbol nativeIntegerType, bool signed)
{
Assert.Empty(nativeIntegerType.GetTypeMembers());
var nativeIntegerMembers = nativeIntegerType.GetMembers();
var underlyingMembers = underlyingType.GetMembers();
var nativeIntegerMemberNames = nativeIntegerType.MemberNames;
AssertEx.Equal(nativeIntegerMembers.SelectAsArray(m => m.Name), nativeIntegerMemberNames);
var expectedMembers = underlyingMembers.WhereAsArray(m => includeUnderlyingMember(m)).Sort(SymbolComparison);
var actualMembers = nativeIntegerMembers.WhereAsArray(m => includeNativeIntegerMember(m)).Sort(SymbolComparison);
Assert.Equal(expectedMembers.Length, actualMembers.Length);
for (int i = 0; i < expectedMembers.Length; i++)
{
VerifyMember(actualMembers[i], expectedMembers[i], signed);
}
static bool includeUnderlyingMember(Symbol underlyingMember)
{
if (underlyingMember.DeclaredAccessibility != Accessibility.Public)
{
return false;
}
switch (underlyingMember.Kind)
{
case SymbolKind.Method:
var method = (MethodSymbol)underlyingMember;
if (method.IsGenericMethod)
{
return false;
}
switch (method.MethodKind)
{
case MethodKind.Ordinary:
return !IsSkippedMethodName(method.Name);
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
return includeUnderlyingMember(method.AssociatedSymbol);
default:
return false;
}
case SymbolKind.Property:
var property = (PropertySymbol)underlyingMember;
return property.ParameterCount == 0 && !IsSkippedPropertyName(property.Name);
default:
return false;
}
}
static bool includeNativeIntegerMember(Symbol nativeIntegerMember)
{
return !(nativeIntegerMember is MethodSymbol { MethodKind: MethodKind.Constructor });
}
}
private static void VerifyMembers(NamedTypeSymbol type)
{
var memberNames = type.MemberNames;
var allMembers = type.GetMembers();
Assert.Equal(allMembers, type.GetMembers()); // same array
foreach (var member in allMembers)
{
Assert.Contains(member.Name, memberNames);
verifyMember(type, member);
}
var unorderedMembers = type.GetMembersUnordered();
Assert.Equal(allMembers.Length, unorderedMembers.Length);
verifyMembers(type, allMembers, unorderedMembers);
foreach (var memberName in memberNames)
{
var members = type.GetMembers(memberName);
Assert.False(members.IsDefaultOrEmpty);
verifyMembers(type, allMembers, members);
}
static void verifyMembers(NamedTypeSymbol type, ImmutableArray allMembers, ImmutableArray members)
{
foreach (var member in members)
{
Assert.Contains(member, allMembers);
verifyMember(type, member);
}
}
static void verifyMember(NamedTypeSymbol type, Symbol member)
{
Assert.Same(type, member.ContainingSymbol);
Assert.Same(type, member.ContainingType);
if (member is MethodSymbol method)
{
var parameters = method.Parameters;
Assert.Equal(parameters, method.Parameters); // same array
}
}
}
private static void VerifyMembers(INamedTypeSymbol type)
{
var memberNames = type.MemberNames;
var allMembers = type.GetMembers();
Assert.Equal(allMembers, type.GetMembers(), ReferenceEqualityComparer.Instance); // same member instances
foreach (var member in allMembers)
{
Assert.Contains(member.Name, memberNames);
verifyMember(type, member);
}
foreach (var memberName in memberNames)
{
var members = type.GetMembers(memberName);
Assert.False(members.IsDefaultOrEmpty);
verifyMembers(type, allMembers, members);
}
static void verifyMembers(INamedTypeSymbol type, ImmutableArray allMembers, ImmutableArray members)
{
foreach (var member in members)
{
Assert.Contains(member, allMembers);
verifyMember(type, member);
}
}
static void verifyMember(INamedTypeSymbol type, ISymbol member)
{
Assert.Same(type, member.ContainingSymbol);
Assert.Same(type, member.ContainingType);
}
}
private static void VerifyMember(Symbol member, Symbol underlyingMember, bool signed)
{
var specialType = signed ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr;
Assert.Equal(member.Name, underlyingMember.Name);
Assert.Equal(member.DeclaredAccessibility, underlyingMember.DeclaredAccessibility);
Assert.Equal(member.IsStatic, underlyingMember.IsStatic);
Assert.NotEqual(member, underlyingMember);
Assert.True(member.Equals(underlyingMember, TypeCompareKind.IgnoreNativeIntegers));
Assert.False(member.Equals(underlyingMember, TypeCompareKind.ConsiderEverything));
Assert.Same(underlyingMember, getUnderlyingMember(member));
Assert.Equal(member.GetHashCode(), underlyingMember.GetHashCode());
switch (member.Kind)
{
case SymbolKind.Method:
{
var method = (MethodSymbol)member;
var underlyingMethod = (MethodSymbol)underlyingMember;
verifyTypes(method.ReturnTypeWithAnnotations, underlyingMethod.ReturnTypeWithAnnotations);
for (int i = 0; i < method.ParameterCount; i++)
{
VerifyMember(method.Parameters[i], underlyingMethod.Parameters[i], signed);
}
}
break;
case SymbolKind.Property:
{
var property = (PropertySymbol)member;
var underlyingProperty = (PropertySymbol)underlyingMember;
verifyTypes(property.TypeWithAnnotations, underlyingProperty.TypeWithAnnotations);
}
break;
case SymbolKind.Parameter:
{
var parameter = (ParameterSymbol)member;
var underlyingParameter = (ParameterSymbol)underlyingMember;
verifyTypes(parameter.TypeWithAnnotations, underlyingParameter.TypeWithAnnotations);
}
break;
default:
throw ExceptionUtilities.UnexpectedValue(member.Kind);
}
var explicitImplementations = member.GetExplicitInterfaceImplementations();
Assert.Equal(0, explicitImplementations.Length);
void verifyTypes(TypeWithAnnotations fromMember, TypeWithAnnotations fromUnderlyingMember)
{
Assert.True(fromMember.Equals(fromUnderlyingMember, TypeCompareKind.IgnoreNativeIntegers));
// No use of underlying type in native integer member.
Assert.False(containsType(fromMember, useNativeInteger: false));
// No use of native integer in underlying member.
Assert.False(containsType(fromUnderlyingMember, useNativeInteger: true));
// Use of underlying type in underlying member should match use of native type in native integer member.
Assert.Equal(containsType(fromMember, useNativeInteger: true), containsType(fromUnderlyingMember, useNativeInteger: false));
Assert.NotEqual(containsType(fromMember, useNativeInteger: true), fromMember.Equals(fromUnderlyingMember, TypeCompareKind.ConsiderEverything));
}
bool containsType(TypeWithAnnotations type, bool useNativeInteger)
{
return type.Type.VisitType((type, unused1, unused2) => type.SpecialType == specialType && useNativeInteger == type.IsNativeIntegerType, (object)null) is { };
}
static Symbol getUnderlyingMember(Symbol nativeIntegerMember)
{
switch (nativeIntegerMember.Kind)
{
case SymbolKind.Method:
return ((WrappedMethodSymbol)nativeIntegerMember).UnderlyingMethod;
case SymbolKind.Property:
return ((WrappedPropertySymbol)nativeIntegerMember).UnderlyingProperty;
case SymbolKind.Parameter:
return ((WrappedParameterSymbol)nativeIntegerMember).UnderlyingParameter;
default:
throw ExceptionUtilities.UnexpectedValue(nativeIntegerMember.Kind);
}
}
}
private static bool IsSkippedMethodName(string name)
{
switch (name)
{
case "Add":
case "Subtract":
case "ToInt32":
case "ToInt64":
case "ToUInt32":
case "ToUInt64":
case "ToPointer":
return true;
default:
return false;
}
}
private static bool IsSkippedPropertyName(string name)
{
switch (name)
{
case "Size":
return true;
default:
return false;
}
}
private static int SymbolComparison(Symbol x, Symbol y) => SymbolComparison(x.ToTestDisplayString(), y.ToTestDisplayString());
private static int SymbolComparison(ISymbol x, ISymbol y) => SymbolComparison(x.ToTestDisplayString(), y.ToTestDisplayString());
private static int SymbolComparison(string x, string y)
{
return string.CompareOrdinal(normalizeDisplayString(x), normalizeDisplayString(y));
static string normalizeDisplayString(string s) => s.Replace("System.IntPtr", "nint").Replace("System.UIntPtr", "nuint");
}
[Fact]
public void MissingTypes()
{
var sourceA =
@"namespace System
{
public class Object { }
public abstract class ValueType { }
public struct Void { }
}";
var sourceB =
@"interface I
{
void F1(System.IntPtr x, nint y);
void F2(System.UIntPtr x, nuint y);
}";
var diagnostics = new[]
{
// (3,20): error CS0234: The underlyingType or namespace name 'IntPtr' does not exist in the namespace 'System' (are you missing an assembly reference?)
// void F1(System.IntPtr x, nint y);
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "IntPtr").WithArguments("IntPtr", "System").WithLocation(3, 20),
// (3,30): error CS0518: Predefined underlyingType 'System.IntPtr' is not defined or imported
// void F1(System.IntPtr x, nint y);
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "nint").WithArguments("System.IntPtr").WithLocation(3, 30),
// (4,20): error CS0234: The underlyingType or namespace name 'UIntPtr' does not exist in the namespace 'System' (are you missing an assembly reference?)
// void F2(System.UIntPtr x, nuint y);
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "UIntPtr").WithArguments("UIntPtr", "System").WithLocation(4, 20),
// (4,31): error CS0518: Predefined underlyingType 'System.UIntPtr' is not defined or imported
// void F2(System.UIntPtr x, nuint y);
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "nuint").WithArguments("System.UIntPtr").WithLocation(4, 31)
};
var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(diagnostics);
verify(comp);
comp = CreateEmptyCompilation(sourceA);
comp.VerifyDiagnostics();
var ref1 = comp.ToMetadataReference();
var ref2 = comp.EmitToImageReference();
comp = CreateEmptyCompilation(sourceB, references: new[] { ref1 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(diagnostics);
verify(comp);
comp = CreateEmptyCompilation(sourceB, references: new[] { ref2 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(diagnostics);
verify(comp);
static void verify(CSharpCompilation comp)
{
var method = comp.GetMember("I.F1");
Assert.Equal("void I.F1(System.IntPtr x, nint y)", method.ToTestDisplayString());
VerifyErrorTypes((NamedTypeSymbol)method.Parameters[0].Type, (NamedTypeSymbol)method.Parameters[1].Type, signed: true);
method = comp.GetMember("I.F2");
Assert.Equal("void I.F2(System.UIntPtr x, nuint y)", method.ToTestDisplayString());
VerifyErrorTypes((NamedTypeSymbol)method.Parameters[0].Type, (NamedTypeSymbol)method.Parameters[1].Type, signed: false);
}
}
private static void VerifyErrorType(NamedTypeSymbol type, SpecialType specialType, bool isNativeInt)
{
Assert.Equal(SymbolKind.ErrorType, type.Kind);
Assert.Equal(TypeKind.Error, type.TypeKind);
Assert.Equal(isNativeInt, type.IsNativeIntegerType);
Assert.Equal(specialType, type.SpecialType);
}
private static void VerifyErrorType(INamedTypeSymbol type, SpecialType specialType, bool isNativeInt)
{
Assert.Equal(SymbolKind.ErrorType, type.Kind);
Assert.Equal(TypeKind.Error, type.TypeKind);
Assert.Equal(isNativeInt, type.IsNativeIntegerType);
Assert.Equal(specialType, type.SpecialType);
}
private static void VerifyErrorTypes(NamedTypeSymbol underlyingType, NamedTypeSymbol nativeIntegerType, bool signed)
{
var specialType = signed ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr;
VerifyErrorType(underlyingType, SpecialType.None, isNativeInt: false);
VerifyErrorType(nativeIntegerType, specialType, isNativeInt: true);
Assert.Null(underlyingType.NativeIntegerUnderlyingType);
VerifyErrorType(nativeIntegerType.NativeIntegerUnderlyingType, specialType, isNativeInt: false);
VerifyEqualButDistinct(nativeIntegerType.NativeIntegerUnderlyingType, nativeIntegerType);
VerifyErrorTypes(underlyingType.GetPublicSymbol(), nativeIntegerType.GetPublicSymbol(), signed);
}
private static void VerifyErrorTypes(INamedTypeSymbol underlyingType, INamedTypeSymbol nativeIntegerType, bool signed)
{
var specialType = signed ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr;
VerifyErrorType(underlyingType, SpecialType.None, isNativeInt: false);
VerifyErrorType(nativeIntegerType, specialType, isNativeInt: true);
Assert.Null(underlyingType.NativeIntegerUnderlyingType);
VerifyErrorType(nativeIntegerType.NativeIntegerUnderlyingType, specialType, isNativeInt: false);
}
[Fact]
public void Retargeting_01()
{
var sourceA =
@"public class A
{
public static nint F1 = int.MinValue;
public static nuint F2 = int.MaxValue;
public static nint F3 = -1;
public static nuint F4 = 1;
}";
var comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Mscorlib40);
var refA = comp.ToMetadataReference();
var typeA = comp.GetMember("A.F1").Type;
var corLibA = comp.Assembly.CorLibrary;
Assert.Equal(corLibA, typeA.ContainingAssembly);
var sourceB =
@"class B : A
{
static void Main()
{
System.Console.WriteLine(""{0}, {1}, {2}, {3}"", F1, F2, F3, F4);
}
}";
comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Mscorlib45);
CompileAndVerify(comp, expectedOutput: $"{int.MinValue}, {int.MaxValue}, -1, 1");
var corLibB = comp.Assembly.CorLibrary;
Assert.NotEqual(corLibA, corLibB);
var f1 = comp.GetMember("A.F1");
verifyField(f1, "nint A.F1", corLibB);
var f2 = comp.GetMember("A.F2");
verifyField(f2, "nuint A.F2", corLibB);
var f3 = comp.GetMember("A.F3");
verifyField(f3, "nint A.F3", corLibB);
var f4 = comp.GetMember("A.F4");
verifyField(f4, "nuint A.F4", corLibB);
Assert.Same(f1.Type, f3.Type);
Assert.Same(f2.Type, f4.Type);
static void verifyField(FieldSymbol field, string expectedSymbol, AssemblySymbol expectedAssembly)
{
Assert.IsType(field);
Assert.Equal(expectedSymbol, field.ToTestDisplayString());
var type = (NamedTypeSymbol)field.Type;
Assert.True(type.IsNativeIntegerType);
Assert.IsType(type);
Assert.Equal(expectedAssembly, type.NativeIntegerUnderlyingType.ContainingAssembly);
}
}
[Fact]
public void Retargeting_02()
{
var source1 =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public struct IntPtr { }
public struct UIntPtr { }
}";
var assemblyName = GetUniqueName();
var comp = CreateCompilation(new AssemblyIdentity(assemblyName, new Version(1, 0, 0, 0)), new[] { source1 }, references: null);
var ref1 = comp.EmitToImageReference();
var sourceA =
@"public class A
{
public static nint F1 = -1;
public static nuint F2 = 1;
public static nint F3 = -2;
public static nuint F4 = 2;
}";
comp = CreateEmptyCompilation(sourceA, references: new[] { ref1 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
var refA = comp.ToMetadataReference();
var typeA = comp.GetMember("A.F1").Type;
var corLibA = comp.Assembly.CorLibrary;
Assert.Equal(corLibA, typeA.ContainingAssembly);
var source2 =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
}";
comp = CreateCompilation(new AssemblyIdentity(assemblyName, new Version(2, 0, 0, 0)), new[] { source2 }, references: null);
var ref2 = comp.EmitToImageReference();
var sourceB =
@"class B : A
{
static void Main()
{
_ = F1;
_ = F2;
}
}";
comp = CreateEmptyCompilation(sourceB, references: new[] { ref2, refA }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(
// (5,13): error CS0518: Predefined type 'System.IntPtr' is not defined or imported
// _ = F1;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F1").WithArguments("System.IntPtr").WithLocation(5, 13),
// (6,13): error CS0518: Predefined type 'System.UIntPtr' is not defined or imported
// _ = F2;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F2").WithArguments("System.UIntPtr").WithLocation(6, 13));
var corLibB = comp.Assembly.CorLibrary;
Assert.NotEqual(corLibA, corLibB);
var f1 = comp.GetMember("A.F1");
verifyField(f1, "nint A.F1", corLibB);
var f2 = comp.GetMember("A.F2");
verifyField(f2, "nuint A.F2", corLibB);
var f3 = comp.GetMember("A.F3");
verifyField(f3, "nint A.F3", corLibB);
var f4 = comp.GetMember("A.F4");
verifyField(f4, "nuint A.F4", corLibB);
// MissingMetadataTypeSymbol.TopLevel instances are not reused.
Assert.Equal(f1.Type, f3.Type);
Assert.NotSame(f1.Type, f3.Type);
Assert.Equal(f2.Type, f4.Type);
Assert.NotSame(f2.Type, f4.Type);
static void verifyField(FieldSymbol field, string expectedSymbol, AssemblySymbol expectedAssembly)
{
Assert.IsType(field);
Assert.Equal(expectedSymbol, field.ToTestDisplayString());
var type = (NamedTypeSymbol)field.Type;
Assert.True(type.IsNativeIntegerType);
Assert.IsType(type);
Assert.Equal(expectedAssembly, type.NativeIntegerUnderlyingType.ContainingAssembly);
}
}
[Fact]
public void Retargeting_03()
{
var source1 =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
}";
var assemblyName = GetUniqueName();
var comp = CreateCompilation(new AssemblyIdentity(assemblyName, new Version(1, 0, 0, 0)), new[] { source1 }, references: null);
var ref1 = comp.EmitToImageReference();
var sourceA =
@"public class A
{
public static nint F1 = -1;
public static nuint F2 = 1;
}";
comp = CreateEmptyCompilation(sourceA, references: new[] { ref1 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(
// (3,19): error CS0518: Predefined type 'System.IntPtr' is not defined or imported
// public static nint F1 = -1;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "nint").WithArguments("System.IntPtr").WithLocation(3, 19),
// (4,19): error CS0518: Predefined type 'System.UIntPtr' is not defined or imported
// public static nuint F2 = 1;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "nuint").WithArguments("System.UIntPtr").WithLocation(4, 19));
var refA = comp.ToMetadataReference();
var typeA = comp.GetMember("A.F1").Type;
var corLibA = comp.Assembly.CorLibrary;
Assert.Equal(corLibA, typeA.ContainingAssembly);
var source2 =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public struct IntPtr { }
public struct UIntPtr { }
}";
comp = CreateCompilation(new AssemblyIdentity(assemblyName, new Version(2, 0, 0, 0)), new[] { source2 }, references: null);
var ref2 = comp.EmitToImageReference();
var sourceB =
@"class B : A
{
static void Main()
{
_ = F1;
_ = F2;
}
}";
comp = CreateEmptyCompilation(sourceB, references: new[] { ref2, refA }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(
// (5,13): error CS0518: Predefined type 'System.IntPtr' is not defined or imported
// _ = F1;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F1").WithArguments("System.IntPtr").WithLocation(5, 13),
// (6,13): error CS0518: Predefined type 'System.UIntPtr' is not defined or imported
// _ = F2;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F2").WithArguments("System.UIntPtr").WithLocation(6, 13));
var corLibB = comp.Assembly.CorLibrary;
Assert.NotEqual(corLibA, corLibB);
var f1 = comp.GetMember("A.F1");
verifyField(f1, "nint A.F1", corLibA);
var f2 = comp.GetMember("A.F2");
verifyField(f2, "nuint A.F2", corLibA);
static void verifyField(FieldSymbol field, string expectedSymbol, AssemblySymbol expectedAssembly)
{
Assert.IsType(field);
Assert.Equal(expectedSymbol, field.ToTestDisplayString());
var type = (NamedTypeSymbol)field.Type;
Assert.True(type.IsNativeIntegerType);
Assert.IsType(type);
Assert.Equal(expectedAssembly, type.NativeIntegerUnderlyingType.ContainingAssembly);
}
}
[Fact]
public void Retargeting_04()
{
var sourceA =
@"public class A
{
}";
var assemblyName = GetUniqueName();
var references = TargetFrameworkUtil.GetReferences(TargetFramework.Standard).ToArray();
var comp = CreateCompilation(new AssemblyIdentity(assemblyName, new Version(1, 0, 0, 0)), new[] { sourceA }, references: references);
var refA1 = comp.EmitToImageReference();
comp = CreateCompilation(new AssemblyIdentity(assemblyName, new Version(2, 0, 0, 0)), new[] { sourceA }, references: references);
var refA2 = comp.EmitToImageReference();
var sourceB =
@"public class B
{
public static A F0 = new A();
public static nint F1 = int.MinValue;
public static nuint F2 = int.MaxValue;
public static nint F3 = -1;
public static nuint F4 = 1;
}";
comp = CreateCompilation(sourceB, references: new[] { refA1 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Standard);
var refB = comp.ToMetadataReference();
var f0B = comp.GetMember("B.F0");
var t1B = comp.GetMember("B.F1").Type;
var t2B = comp.GetMember("B.F2").Type;
var sourceC =
@"class C : B
{
static void Main()
{
_ = F0;
_ = F1;
_ = F2;
}
}";
comp = CreateCompilation(sourceC, references: new[] { refA2, refB }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Standard);
comp.VerifyDiagnostics();
var f0 = comp.GetMember("B.F0");
Assert.NotEqual(f0B.Type.ContainingAssembly, f0.Type.ContainingAssembly);
Assert.IsType(f0);
var f1 = comp.GetMember("B.F1");
verifyField(f1, "nint B.F1");
var f2 = comp.GetMember("B.F2");
verifyField(f2, "nuint B.F2");
var f3 = comp.GetMember("B.F3");
verifyField(f3, "nint B.F3");
var f4 = comp.GetMember("B.F4");
verifyField(f4, "nuint B.F4");
Assert.Same(t1B, f1.Type);
Assert.Same(t2B, f2.Type);
Assert.Same(f1.Type, f3.Type);
Assert.Same(f2.Type, f4.Type);
static void verifyField(FieldSymbol field, string expectedSymbol)
{
Assert.IsType(field);
Assert.Equal(expectedSymbol, field.ToTestDisplayString());
var type = (NamedTypeSymbol)field.Type;
Assert.True(type.IsNativeIntegerType);
Assert.IsType(type);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Retargeting_05(bool useCompilationReference)
{
var source1 =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public struct Enum { }
public class Attribute { }
public class AttributeUsageAttribute : Attribute
{
public AttributeUsageAttribute(AttributeTargets validOn) { }
public bool AllowMultiple { get; set; }
public bool Inherited { get; set; }
}
public enum AttributeTargets { }
public struct IntPtr { }
public struct UIntPtr { }
}";
var comp = CreateCompilation(new AssemblyIdentity("9ef8b1e0-1ae0-4af6-b9a1-00f2078f299e", new Version(1, 0, 0, 0)), new[] { source1 }, references: null);
var ref1 = comp.EmitToImageReference(EmitOptions.Default.WithRuntimeMetadataVersion("0.0.0.0"));
var sourceA =
@"public abstract class A
{
public abstract void F() where U : T;
}
public class B : A
{
public override void F() { }
}";
comp = CreateEmptyCompilation(sourceA, references: new[] { ref1 }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
var refA = AsReference(comp, useCompilationReference);
var type1 = getConstraintType(comp);
Assert.True(type1.IsNativeIntegerType);
Assert.False(type1.IsErrorType());
var sourceB =
@"class C : B
{
}";
comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(
// (1,7): error CS0518: Predefined type 'System.Void' is not defined or imported
// class C : B
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C").WithArguments("System.Void").WithLocation(1, 7),
// (1,11): error CS0518: Predefined type 'System.IntPtr' is not defined or imported
// class C : B
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "B").WithArguments("System.IntPtr").WithLocation(1, 11),
// (1,11): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly '9ef8b1e0-1ae0-4af6-b9a1-00f2078f299e, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
// class C : B
Diagnostic(ErrorCode.ERR_NoTypeDef, "B").WithArguments("System.Object", "9ef8b1e0-1ae0-4af6-b9a1-00f2078f299e, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 11));
var type2 = getConstraintType(comp);
Assert.True(type2.ContainingAssembly.IsMissing);
Assert.False(type2.IsNativeIntegerType);
Assert.True(type2.IsErrorType());
static TypeSymbol getConstraintType(CSharpCompilation comp) =>
comp.GetMember("B.F").TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].Type;
}
[Fact]
public void Retargeting_06()
{
var source1 =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public class IntPtr { }
public class UIntPtr { }
}";
var comp = CreateCompilation(new AssemblyIdentity("c804cc09-8f73-44a1-9cfe-9567bed1def6", new Version(1, 0, 0, 0)), new[] { source1 }, references: null);
var ref1 = comp.EmitToImageReference();
var sourceA =
@"public class A : nint
{
}";
comp = CreateEmptyCompilation(sourceA, references: new[] { ref1 }, parseOptions: TestOptions.Regular9);
var refA = comp.ToMetadataReference();
var typeA = comp.GetMember("A").BaseTypeNoUseSiteDiagnostics;
Assert.True(typeA.IsNativeIntegerType);
Assert.False(typeA.IsErrorType());
var sourceB =
@"class B : A
{
}";
comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics(
// (1,7): error CS0518: Predefined type 'System.Void' is not defined or imported
// class B : A
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "B").WithArguments("System.Void").WithLocation(1, 7),
// (1,11): error CS0012: The type 'IntPtr' is defined in an assembly that is not referenced. You must add a reference to assembly 'c804cc09-8f73-44a1-9cfe-9567bed1def6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
// class B : A
Diagnostic(ErrorCode.ERR_NoTypeDef, "A").WithArguments("System.IntPtr", "c804cc09-8f73-44a1-9cfe-9567bed1def6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 11));
var typeB = comp.GetMember("A").BaseTypeNoUseSiteDiagnostics;
Assert.True(typeB.ContainingAssembly.IsMissing);
Assert.False(typeB.IsNativeIntegerType);
Assert.True(typeB.IsErrorType());
}
[Fact]
public void Interfaces()
{
var sourceA =
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public interface ISerializable { }
public interface IEquatable
{
bool Equals(T other);
}
public interface IOther { }
public struct IntPtr : ISerializable, IEquatable, IOther
{
bool IEquatable.Equals(IntPtr other) => false;
}
}";
var sourceB =
@"using System;
class Program
{
static void F0(ISerializable i) { }
static object F1(IEquatable i) => default;
static void F2(IEquatable i) { }
static void F3(IOther i) { }
static void Main()
{
nint n = 42;
F0(n);
F1(n);
F2(n);
F3(n);
F3(n);
F3((IntPtr)n);
}
}";
var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
}
[Fact]
public void IEquatable()
{
// Minimal definitions.
verifyAll(includesIEquatable: true,
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public interface IEquatable { }
public struct IntPtr : IEquatable { }
public struct UIntPtr : IEquatable { }
}");
// IEquatable in global namespace.
verifyAll(includesIEquatable: false,
@"public interface IEquatable { }
namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public struct IntPtr : IEquatable { }
public struct UIntPtr : IEquatable { }
}");
// IEquatable in other namespace.
verifyAll(includesIEquatable: false,
@"namespace Other
{
public interface IEquatable { }
}
namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public struct IntPtr : Other.IEquatable { }
public struct UIntPtr : Other.IEquatable { }
}");
// IEquatable nested in "System" type.
verifyAll(includesIEquatable: false,
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public class System
{
public interface IEquatable { }
}
public struct IntPtr : System.IEquatable { }
public struct UIntPtr : System.IEquatable { }
}");
// IEquatable nested in other type.
verifyAll(includesIEquatable: false,
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public class Other
{
public interface IEquatable { }
}
public struct IntPtr : Other.IEquatable { }
public struct UIntPtr : Other.IEquatable { }
}");
// IEquatable.
verifyAll(includesIEquatable: false,
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public interface IEquatable { }
public struct IntPtr : IEquatable { }
public struct UIntPtr : IEquatable { }
}");
// IEquatable.
verifyAll(includesIEquatable: false,
@"namespace System
{
public class Object { }
public class String { }
public abstract class ValueType { }
public struct Void { }
public struct Boolean { }
public struct Int32 { }
public interface IEquatable { }
public struct IntPtr : IEquatable { }
public struct UIntPtr : IEquatable { }
}");
// IEquatable