diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs
index 9a29c28543718f26dee6972248e1fe64568e8582..141809ba95f6c9d2f0653838eb62afed9864e88a 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs
@@ -48,24 +48,24 @@ internal static class CustomModifierUtils
TypeSymbol returnTypeWithCustomModifiers = constructedSourceMethod.ReturnType;
if (returnType.Equals(returnTypeWithCustomModifiers, TypeCompareKind.AllIgnoreOptions))
{
- returnType = CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnType, RefKind.None, destinationMethod.ContainingAssembly);
+ returnType = CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnType, destinationMethod.ContainingAssembly);
}
}
/// Type that already has custom modifiers.
/// Same as , but without custom modifiers. May differ in object/dynamic.
- /// of the parameter of which this is the type (or for a return type.
/// The assembly containing the signature referring to the destination type.
/// with custom modifiers copied from .
- internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, RefKind refKind, AssemblySymbol containingAssembly)
+ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, AssemblySymbol containingAssembly)
{
Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions));
// NOTE: overrides can differ by object/dynamic. If they do, we'll need to tweak newType before
// we can use it in place of this.Type. We do so by computing the dynamic transform flags that
// code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
- ImmutableArray flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
- TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);
+ // NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context
+ ImmutableArray flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, RefKind.None);
+ TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, RefKind.None, flags);
TypeSymbol resultType;
if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs
index aaddddb6deb2f2a20c64b2e01eec701529a14494..d4e037438f45ed040610cece0ada3d8077008a0d 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs
@@ -533,7 +533,7 @@ protected static void CopyEventCustomModifiers(EventSymbol eventWithCustomModifi
// we want to retain the original (incorrect) type to avoid hiding the type given in source.
if (type.Equals(overriddenEventType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
{
- type = CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type, RefKind.None, containingAssembly);
+ type = CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type, containingAssembly);
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs
index c5e3bd5528393b5e6f66ba215c6bd0917ad3bd8d..d081bd7af0e47457a1a65e311c138ff23d865fcf 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs
@@ -113,7 +113,7 @@ internal override ParameterSymbol WithCustomModifiersAndParams(TypeSymbol newTyp
internal SourceParameterSymbol WithCustomModifiersAndParamsCore(TypeSymbol newType, ImmutableArray newCustomModifiers, ushort countOfCustomModifiersPrecedingByRef, bool newIsParams)
{
- newType = CustomModifierUtils.CopyTypeCustomModifiers(newType, this.Type, _refKind, this.ContainingAssembly);
+ newType = CustomModifierUtils.CopyTypeCustomModifiers(newType, this.Type, this.ContainingAssembly);
if (newCustomModifiers.IsDefaultOrEmpty)
{
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs
index 9547cf7a41c96c7ace30fb9923c523082313dd37..0d5e8efe4ad7001f01450f46c5c1ecb98b3b0a81 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs
@@ -281,7 +281,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
else if (_lazyReturnType.SpecialType != SpecialType.System_Void)
{
PropertySymbol associatedProperty = _property;
- _lazyReturnType = CustomModifierUtils.CopyTypeCustomModifiers(associatedProperty.Type, _lazyReturnType, RefKind.None, this.ContainingAssembly);
+ _lazyReturnType = CustomModifierUtils.CopyTypeCustomModifiers(associatedProperty.Type, _lazyReturnType, this.ContainingAssembly);
_lazyReturnTypeCustomModifiers = associatedProperty.TypeCustomModifiers;
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs
index 78cf0766b88c8589e92d301cd8e6c965761039ff..b8471a8b77f194f6453770a32d2eaaa48e5c034d 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs
@@ -245,7 +245,7 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym
// we want to retain the original (incorrect) type to avoid hiding the type given in source.
if (_lazyType.Equals(overriddenPropertyType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
{
- _lazyType = CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType, _lazyType, RefKind.None, this.ContainingAssembly);
+ _lazyType = CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType, _lazyType, this.ContainingAssembly);
}
_lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
index ad346d167871c6baae7638d44b47ae4be0fa8b36..efd6c8fb24cab3f5fff64ccd20148245bf90ff44 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
@@ -19385,8 +19385,10 @@ public class B1
comp1.VerifyDiagnostics();
}
+ [WorkItem(14708, "https://github.com/dotnet/roslyn/issues/14708")]
+ [WorkItem(14709, "https://github.com/dotnet/roslyn/issues/14709")]
[Fact]
- public void Regress001()
+ public void RefTupleDynamicDecode001()
{
string lib = @"
@@ -19431,8 +19433,10 @@ public override ref (int, object) Foo(int arg)
var comp = CompileAndVerify(source, expectedOutput: "42qq", additionalRefs: new[] { libComp.ToMetadataReference() }.Concat(s_valueTupleRefs), options: TestOptions.DebugExe, verify: false);
}
+ [WorkItem(14708, "https://github.com/dotnet/roslyn/issues/14708")]
+ [WorkItem(14709, "https://github.com/dotnet/roslyn/issues/14709")]
[Fact]
- public void Regress002()
+ public void RefTupleDynamicDecode002()
{
string lib = @"
@@ -19721,5 +19725,117 @@ struct BB
--
--");
}
+ [WorkItem(14708, "https://github.com/dotnet/roslyn/issues/14708")]
+ [WorkItem(14709, "https://github.com/dotnet/roslyn/issues/14709")]
+ [Fact]
+ public void RefTupleDynamicDecode003()
+ {
+ string lib = @"
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly extern System.Core
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly extern System.ValueTuple
+{
+ .publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) // .{...-.Q
+ .ver 4:0:1:0
+}
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi beforefieldinit ClassLibrary1.C1
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype [System.ValueTuple]System.ValueTuple`2&
+ Foo(int32 arg) cil managed
+ {
+ .param [0]
+ // the dynamic flags array is too short - decoder expects a flag matching ""ref"", but it is missing here.
+ .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor(bool[]) = ( 01 00 03 00 00 00 00 00 01 00 00 )
+ // Code size 37 (0x25)
+ .maxstack 5
+ .locals init (valuetype [System.ValueTuple]System.ValueTuple`2& V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.1
+ IL_0002: newarr valuetype [System.ValueTuple]System.ValueTuple`2
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldc.i4.1
+ IL_000a: ldarg.1
+ IL_000b: box [mscorlib]System.Int32
+ IL_0010: newobj instance void valuetype [System.ValueTuple]System.ValueTuple`2::.ctor(!0,
+ !1)
+ IL_0015: stelem valuetype [System.ValueTuple]System.ValueTuple`2
+ IL_001a: ldc.i4.0
+ IL_001b: ldelema valuetype [System.ValueTuple]System.ValueTuple`2
+ IL_0020: stloc.0
+ IL_0021: br.s IL_0023
+
+ IL_0023: ldloc.0
+ IL_0024: ret
+ } // end of method C1::Foo
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method C1::.ctor
+
+} // end of class ClassLibrary1.C1
+";
+ var libCompRef = CompileIL(lib);
+
+ var source = @"
+namespace ConsoleApplication5
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ ref var x = ref new C2().Foo(42);
+ System.Console.Write(x.Item2);
+ x.Item2 = ""qq"";
+ System.Console.WriteLine(x.Item2);
+ }
+ }
+
+ class C2: ClassLibrary1.C1
+ {
+ public override ref (int, dynamic) Foo(int arg)
+ {
+ return ref base.Foo(arg);
+ }
+ }
+}
+";
+
+ var comp = CreateCompilationWithMscorlib45AndCSruntime(source, additionalRefs: new[] { libCompRef }.Concat(s_valueTupleRefs).ToArray(), options: TestOptions.DebugExe);
+
+ CompileAndVerify(comp, expectedOutput: "42qq", verify: false);
+
+ var m = (MethodSymbol)(comp.GetTypeByMetadataName("ConsoleApplication5.C2").GetMembers("Foo").First());
+ Assert.Equal("ref (System.Int32, dynamic) ConsoleApplication5.C2.Foo(System.Int32 arg)", m.ToTestDisplayString());
+
+ var b = m.OverriddenMethod;
+ // not (int, dynamic),
+ // since dynamic flags were not aligned we ignored flags
+ Assert.Equal("ref (System.Int32, System.Object) ClassLibrary1.C1.Foo(System.Int32 arg)", b.ToTestDisplayString());
+
+ }
+
}
}
\ No newline at end of file