未验证 提交 60dc82d8 编写于 作者: C Charles Stoner 提交者: GitHub

Consider NativeIntegerAttribute in CopyTypeCustomModifiers() (#47536)

上级 697f1348
...@@ -23,7 +23,7 @@ internal static TypeSymbol TransformType(TypeSymbol type, EntityHandle handle, P ...@@ -23,7 +23,7 @@ internal static TypeSymbol TransformType(TypeSymbol type, EntityHandle handle, P
type; type;
} }
private static TypeSymbol TransformType(TypeSymbol type, ImmutableArray<bool> transformFlags) internal static TypeSymbol TransformType(TypeSymbol type, ImmutableArray<bool> transformFlags)
{ {
var decoder = new NativeIntegerTypeDecoder(transformFlags); var decoder = new NativeIntegerTypeDecoder(transformFlags);
try try
...@@ -104,7 +104,12 @@ private NamedTypeSymbol TransformNamedType(NamedTypeSymbol type) ...@@ -104,7 +104,12 @@ private NamedTypeSymbol TransformNamedType(NamedTypeSymbol type)
{ {
throw new UnsupportedSignatureContent(); throw new UnsupportedSignatureContent();
} }
return _transformFlags[_index++] ? type.AsNativeInteger() : type; return (_transformFlags[_index++], type.IsNativeIntegerType) switch
{
(false, true) => type.NativeIntegerUnderlyingType,
(true, false) => type.AsNativeInteger(),
_ => type,
};
} }
} }
......
...@@ -74,18 +74,17 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy ...@@ -74,18 +74,17 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy
// code gen uses and then passing them to the dynamic type decoder that metadata reading uses. // code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
// NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context // NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context
ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind); ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags); TypeSymbol resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);
var builder = ArrayBuilder<bool>.GetInstance();
CSharpCompilation.NativeIntegerTransformsEncoder.Encode(builder, destinationType);
resultType = NativeIntegerTypeDecoder.TransformType(resultType, builder.ToImmutableAndFree());
TypeSymbol resultType;
if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic)) if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic))
{ {
// We also preserve tuple names, if present and different // We also preserve tuple names, if present and different
ImmutableArray<string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType); ImmutableArray<string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType);
resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithDynamic, names); resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(resultType, names);
}
else
{
resultType = typeWithDynamic;
} }
// Preserve nullable modifiers as well. // Preserve nullable modifiers as well.
...@@ -100,9 +99,9 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy ...@@ -100,9 +99,9 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy
bool transformResult = resultType.ApplyNullableTransforms(defaultTransformFlag: 0, flagsBuilder.ToImmutableAndFree(), ref position, out resultType); bool transformResult = resultType.ApplyNullableTransforms(defaultTransformFlag: 0, flagsBuilder.ToImmutableAndFree(), ref position, out resultType);
Debug.Assert(transformResult && position == length); Debug.Assert(transformResult && position == length);
Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes)); // Same custom modifiers as source type. Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreNativeIntegers)); // Same custom modifiers as source type.
// Same object/dynamic, nullability and tuple names as destination type. // Same object/dynamic, nullability, native integers, and tuple names as destination type.
Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds));
return resultType; return resultType;
......
...@@ -12237,6 +12237,202 @@ static object Execute(Func<object> f) ...@@ -12237,6 +12237,202 @@ static object Execute(Func<object> f)
{(IntPtr.Size == 4 ? "System.OverflowException" : "0")}"); {(IntPtr.Size == 4 ? "System.OverflowException" : "0")}");
} }
[WorkItem(42500, "https://github.com/dotnet/roslyn/issues/42500")]
[Fact]
public void ExplicitImplementationReturnTypeDifferences()
{
string source =
@"struct S<T>
{
}
interface I
{
S<nint> F1();
S<System.IntPtr> F2();
S<nint> F3();
S<System.IntPtr> F4();
}
class C : I
{
S<System.IntPtr> I.F1() => default;
S<nint> I.F2() => default;
S<nint> I.F3() => default;
S<System.IntPtr> I.F4() => default;
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics();
var type = comp.GetTypeByMetadataName("I");
Assert.Equal("S<nint> I.F1()", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("S<System.IntPtr> I.F2()", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("S<nint> I.F3()", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("S<System.IntPtr> I.F4()", type.GetMember("F4").ToTestDisplayString());
type = comp.GetTypeByMetadataName("C");
Assert.Equal("S<System.IntPtr> C.I.F1()", type.GetMember("I.F1").ToTestDisplayString());
Assert.Equal("S<nint> C.I.F2()", type.GetMember("I.F2").ToTestDisplayString());
Assert.Equal("S<nint> C.I.F3()", type.GetMember("I.F3").ToTestDisplayString());
Assert.Equal("S<System.IntPtr> C.I.F4()", type.GetMember("I.F4").ToTestDisplayString());
}
[WorkItem(42500, "https://github.com/dotnet/roslyn/issues/42500")]
[WorkItem(44358, "https://github.com/dotnet/roslyn/issues/44358")]
[Fact]
public void OverrideReturnTypeDifferences()
{
string source =
@"class A
{
public virtual nint[] F1() => null;
public virtual System.IntPtr[] F2() => null;
public virtual nint[] F3() => null;
public virtual System.IntPtr[] F4() => null;
}
class B : A
{
public override System.IntPtr[] F1() => null;
public override nint[] F2() => null;
public override nint[] F3() => null;
public override System.IntPtr[] F4() => null;
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics();
var type = comp.GetTypeByMetadataName("A");
Assert.Equal("nint[] A.F1()", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("System.IntPtr[] A.F2()", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("nint[] A.F3()", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("System.IntPtr[] A.F4()", type.GetMember("F4").ToTestDisplayString());
type = comp.GetTypeByMetadataName("B");
Assert.Equal("System.IntPtr[] B.F1()", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("nint[] B.F2()", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("nint[] B.F3()", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("System.IntPtr[] B.F4()", type.GetMember("F4").ToTestDisplayString());
}
[WorkItem(42500, "https://github.com/dotnet/roslyn/issues/42500")]
[Fact]
public void OverrideParameterTypeCustomModifierDifferences()
{
var sourceA =
@".class private System.Runtime.CompilerServices.NativeIntegerAttribute extends [mscorlib]System.Attribute
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public A
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public virtual void F1(native int modopt(int32) i)
{
.param [1]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = ( 01 00 00 00 )
ret
}
.method public virtual void F2(native int modopt(int32) i)
{
ret
}
.method public virtual void F3(native int modopt(int32) i)
{
.param [1]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = ( 01 00 00 00 )
ret
}
.method public virtual void F4(native int modopt(int32) i)
{
ret
}
}";
var refA = CompileIL(sourceA);
var sourceB =
@"class B : A
{
public override void F1(System.IntPtr i) { }
public override void F2(nint i) { }
public override void F3(nint i) { }
public override void F4(System.IntPtr i) { }
}";
var comp = CreateCompilation(sourceB, new[] { refA }, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics();
var type = comp.GetTypeByMetadataName("A");
Assert.Equal("void A.F1(nint modopt(System.Int32) i)", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("void A.F2(System.IntPtr modopt(System.Int32) i)", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("void A.F3(nint modopt(System.Int32) i)", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("void A.F4(System.IntPtr modopt(System.Int32) i)", type.GetMember("F4").ToTestDisplayString());
type = comp.GetTypeByMetadataName("B");
Assert.Equal("void B.F1(System.IntPtr modopt(System.Int32) i)", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("void B.F2(nint modopt(System.Int32) i)", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("void B.F3(nint modopt(System.Int32) i)", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("void B.F4(System.IntPtr modopt(System.Int32) i)", type.GetMember("F4").ToTestDisplayString());
}
[WorkItem(42500, "https://github.com/dotnet/roslyn/issues/42500")]
[Fact]
public void OverrideReturnTypeCustomModifierDifferences()
{
var sourceA =
@".class private System.Runtime.CompilerServices.NativeIntegerAttribute extends [mscorlib]System.Attribute
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public A
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public virtual native int[] modopt(int32) F1()
{
.param [0]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = ( 01 00 00 00 )
ldnull
throw
}
.method public virtual native int[] modopt(int32) F2()
{
ldnull
throw
}
.method public virtual native int[] modopt(int32) F3()
{
.param [0]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = ( 01 00 00 00 )
ldnull
throw
}
.method public virtual native int[] modopt(int32) F4()
{
ldnull
throw
}
}";
var refA = CompileIL(sourceA);
var sourceB =
@"class B : A
{
public override System.IntPtr[] F1() => default;
public override nint[] F2() => default;
public override nint[] F3() => default;
public override System.IntPtr[] F4() => default;
}";
var comp = CreateCompilation(sourceB, new[] { refA }, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics();
var type = comp.GetTypeByMetadataName("A");
Assert.Equal("nint[] modopt(System.Int32) A.F1()", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("System.IntPtr[] modopt(System.Int32) A.F2()", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("nint[] modopt(System.Int32) A.F3()", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("System.IntPtr[] modopt(System.Int32) A.F4()", type.GetMember("F4").ToTestDisplayString());
type = comp.GetTypeByMetadataName("B");
Assert.Equal("System.IntPtr[] modopt(System.Int32) B.F1()", type.GetMember("F1").ToTestDisplayString());
Assert.Equal("nint[] modopt(System.Int32) B.F2()", type.GetMember("F2").ToTestDisplayString());
Assert.Equal("nint[] modopt(System.Int32) B.F3()", type.GetMember("F3").ToTestDisplayString());
Assert.Equal("System.IntPtr[] modopt(System.Int32) B.F4()", type.GetMember("F4").ToTestDisplayString());
}
[WorkItem(44810, "https://github.com/dotnet/roslyn/issues/44810")] [WorkItem(44810, "https://github.com/dotnet/roslyn/issues/44810")]
[Theory] [Theory]
[InlineData("void*")] [InlineData("void*")]
......
...@@ -2554,11 +2554,10 @@ static void Main() ...@@ -2554,11 +2554,10 @@ static void Main()
[InlineData("(int X, int Y)", "(int X, int Y)", "(System.Int32 X, System.Int32 Y)", "System.ValueTuple`2[System.Int32,System.Int32]", false)] [InlineData("(int X, int Y)", "(int X, int Y)", "(System.Int32 X, System.Int32 Y)", "System.ValueTuple`2[System.Int32,System.Int32]", false)]
[InlineData("nint", "nint", "nint", "System.IntPtr", true)] [InlineData("nint", "nint", "nint", "System.IntPtr", true)]
[InlineData("nint", "nint", "nint", "System.IntPtr", false)] [InlineData("nint", "nint", "nint", "System.IntPtr", false)]
// https://github.com/dotnet/roslyn/issues/42500: CopyTypeCustomModifiers() should copy NativeIntegerAttribute [InlineData("nint", "System.IntPtr", "System.IntPtr", "System.IntPtr", true)]
//[InlineData("nint", "System.IntPtr", "System.IntPtr", "System.IntPtr", true)] [InlineData("nint", "System.IntPtr", "System.IntPtr", "System.IntPtr", false)]
//[InlineData("nint", "System.IntPtr", "System.IntPtr", "System.IntPtr", false)] [InlineData("System.IntPtr", "nint", "nint", "System.IntPtr", true)]
//[InlineData("System.IntPtr", "nint", "nint", "System.IntPtr", true)] [InlineData("System.IntPtr", "nint", "nint", "System.IntPtr", false)]
//[InlineData("System.IntPtr", "nint", "nint", "System.IntPtr", false)]
public void ExplicitImplementationInBaseType_02(string interfaceTypeArg, string baseTypeArg, string expectedTypeArg, string expectedOutput, bool useCompilationReference) public void ExplicitImplementationInBaseType_02(string interfaceTypeArg, string baseTypeArg, string expectedTypeArg, string expectedOutput, bool useCompilationReference)
{ {
var source0 = var source0 =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册