-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider NativeIntegerAttribute in CopyTypeCustomModifiers() #47536
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
// 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); | ||
TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags); | ||
TypeSymbol resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags); | ||
|
||
var builder = ArrayBuilder<bool>.GetInstance(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: consider adding an overload of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be the only use of that overload. Let's add later if there are other uses. In reply to: 485231913 [](ancestors = 485231913) |
||
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)) | ||
{ | ||
// We also preserve tuple names, if present and different | ||
ImmutableArray<string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType); | ||
resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithDynamic, names); | ||
} | ||
else | ||
{ | ||
resultType = typeWithDynamic; | ||
resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(resultType, names); | ||
} | ||
|
||
// Preserve nullable modifiers as well. | ||
|
@@ -100,9 +99,9 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy | |
bool transformResult = resultType.ApplyNullableTransforms(defaultTransformFlag: 0, flagsBuilder.ToImmutableAndFree(), ref position, out resultType); | ||
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)); | ||
|
||
return resultType; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12237,6 +12237,202 @@ static object Execute(Func<object> f) | |
{(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) { } | ||
}"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we complete the four permutations : base has modified IntPtr vs. nint, and override has unmodified IntPt vs. nint? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added all four permutations. Nested cases are covered in the preceding test. In reply to: 485234664 [](ancestors = 485234664) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem with the preceding case is it doesn't have modifiers to copy. Are we even entering the In reply to: 485239131 [](ancestors = 485239131,485234664) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In reply to: 485242939 [](ancestors = 485242939,485239131,485234664) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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")] | ||
[Theory] | ||
[InlineData("void*")] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Consider revising the
<param name="destinationType">
comment on line 63 to delete its last sentence "May differ in object/dynamic.", since there are several other scenarios that this method handles, possibly more in the future, and we don't want to give an impression that object/dynamic is all that we're handling here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated comments in #47576.
In reply to: 490547894 [](ancestors = 490547894)